?
User Interface Application Buisness Logic Presentation Best Producer is the one who consumes its
own product.
"Eating your own dog food" Web Application NO Installing Updates Web Pages Data Template Page API Discovery HAL Hypertext Application Language OPTIONS /SalesInvoicing/api/ HTTP/1.1

{
  "_links": {
    "self": {
      "href": "http://localhost:8180/SalesInvoicing/Api/"
    },
    "proposedinvoice": {
      "href": "http://localhost:8180/SalesInvoicing/Api/proposedinvoice/{id}"      
    },
    "publishedinvoice": {
      "href": "http://localhost:8180/SalesInvoicing/Api/publishedinvoice/{id}"
    },
    "overview": {
      "href": "http://localhost:8180/SalesInvoicing/Api/overview"
    },
    "paid": {
      "href": "http://localhost:8180/SalesInvoicing/Api/invoices/paid"
    },
    "overdue": {
      "href": "http://localhost:8180/SalesInvoicing/Api/invoices/overdue"
    },
    "due": {
      "href": "http://localhost:8180/SalesInvoicing/Api/invoices/due"
    },
    "proposed": {
      "href": "http://localhost:8180/SalesInvoicing/Api/invoices/proposed"
    },
    "create": {
      "href": "http://localhost:8180/SalesInvoicing/Api/proposedinvoice"
    },
    "vats": {
      "href": "http://localhost:8180/SalesInvoicing/Api/vats"
    },
    "vatrates": {
      "href": "http://localhost:8180/SalesInvoicing/Api/vatrates/{yyyy-MM-dd}"
    },
    "customer": {
      "href": "http://localhost:8180/SalesInvoicing/Api/customer/{id}"
    },
    "createcustomer": {
      "href": "http://localhost:8180/SalesInvoicing/Api/customer"
    },
    "customers": {
      "href": "http://localhost:8180/SalesInvoicing/Api/customers"
    },
    "logo": {
      "href": "http://localhost:8180/SalesInvoicing/Api/logo/{fileName}"
    },
    "uploadlogo": {
      "href": "http://localhost:8180/SalesInvoicing/Api/logo"
    },
    "tasks": {
      "href": "http://localhost:8180/SalesInvoicing/Api/tasks"
    },
    "createarticle": {
      "href": "http://localhost:8180/SalesInvoicing/Api/article"
    },
    "article": {
      "href": "http://localhost:8180/SalesInvoicing/Api/article/{id}"
    },
    "articles": {
      "href": "http://localhost:8180/SalesInvoicing/Api/articles"
    },
    "costcenters": {
      "href": "http://localhost:8180/SalesInvoicing/Api/costcenters"
    },
    "costcenter": {
      "href": "http://localhost:8180/SalesInvoicing/Api/costcenter/{id}"
    },
    "revenuetypes": {
      "href": "http://localhost:8180/SalesInvoicing/Api/revenuetypes"
    },
    "revenuetype": {
      "href": "http://localhost:8180/SalesInvoicing/Api/revenuetype/{id}"
    },
    "createemailtemplate": {
      "href": "http://localhost:8180/SalesInvoicing/Api/emailtemplate"
    }
  }
}		
GET /SalesInvoicing/Api/proposedinvoice/bf64c681-73b0-46eb-b1b5-173f0c0f04e9 HTTP/1.1
{
  "_links": {
    "self": {
      "href": "http://localhost:8180/SalesInvoicing/Api/proposedinvoice/bf64c681-73b0-46eb-b1b5-173f0c0f04e9"
    },
    "publish": {
      "href": "http://localhost:8180/SalesInvoicing/Api/proposedinvoice/bf64c681-73b0-46eb-b1b5-173f0c0f04e9/publish"
    },
    "print": {
      "href": "http://localhost:8180/SalesInvoicing/Api/proposedinvoice/bf64c681-73b0-46eb-b1b5-173f0c0f04e9/pdf"
    },
    "delete": {
      "href": "http://localhost:8180/SalesInvoicing/Api/proposedinvoice/bf64c681-73b0-46eb-b1b5-173f0c0f04e9"
    },
    "update": {
      "href": "http://localhost:8180/SalesInvoicing/Api/proposedinvoice/bf64c681-73b0-46eb-b1b5-173f0c0f04e9"
    },
    "timeline": {
      "href": "http://localhost:8180/SalesInvoicing/Api/invoice/bf64c681-73b0-46eb-b1b5-173f0c0f04e9/timeline"
    }
  },	
  "invoiceData": {  
    "customerId": "00e218de-16d0-4c3f-b1b0-a6b41b00abaa",
    "customerCode": "1000",
    "customerName": "Legacy Customer",
    "customerContactPerson": "",
    "customerAddressLine1": "",
    "customerAddressLine2": "",
    "customerPostalCode": "",
    "customerCity": "",
    "customerCountry": "NL",
    "customerVatNumber": null,
    "companyInfo": "Some info",
    "invoiceDate": "2013-04-19T00:00:00Z",
    "dueDate": "2013-05-03T00:00:00Z",
    "reference": "",
    "currencyCode": "EUR",
    "header": "Some header",
    "footer": "Another footer",
    "logoFileName": null,
    "items": [
      {
        "description": "Some cool item",
        "kind": "Taxable",
        "quantity": 123.0,
        "quantityPrecision": 0,
        "quantityHidden": false,
        "pricePerUnit": 123.0,
        "vatId": "ea744167-3a6a-4fd4-babe-4c832cac1a09",
        "articleId": null
      }
    ]
  },
  "totalIncludingVat": 18003.51,
  "totalExcludingVat": 15129.0,
  "lines": [
    {
      "description": "Some cool item",
      "kind": "Taxable",
      "quantity": 123.0,
      "quantityPrecision": 0,
      "quantityHidden": null,
      "pricePerUnit": 123.0,
      "vatName": "V 19%",
      "subtotalIncludingVat": 18003.51,
      "subtotalExcludingVat": 15129.0
    }
  ],
  "vatLines": [
    {
      "vatName": "V 19%",
      "amount": 2874.51
    }
  ],
  "id": "bf64c681-73b0-46eb-b1b5-173f0c0f04e9",
  "created": "2013-04-19T08:58:38.9267608Z",
  "modified": "2013-04-19T08:58:38.9267608Z",
  "modifiedBy": "VALENTYN",
  "version": 1
}			
		
ProposedInvoiceInstanceResource.cs

public class ProposedInvoiceInstanceResource : Resource
{
		....
		public override IEnumerable Links
		{
			get
			{
				const string routeName = ProposedInvoiceInstanceController.RouteName;

				yield return new Link("self", GetUri(routeName));
				yield return new Link("publish", GetUri(routeName, new { action = "publish" }));
				yield return new Link("print", GetUri(ProposedInvoiceInstanceController.RouteName, new { action = "pdf" }));
				yield return new Link("delete", GetUri(routeName));
				yield return new Link("update", GetUri(routeName));
				yield return new Link("timeline", GetUri(TimelineController.RouteName));
				
				if (!String.IsNullOrEmpty(Content.InvoiceData.LogoFileName))
					yield return new Link("logo", GetUri(LogoController.RouteName, new { fileName = Content.InvoiceData.LogoFileName }));
			}
		}		
}
		
	
Internationalization dashboard.cshtml

<section class="content-panel">
  <div class="title">@Common.Sales</div>
    <div class="fill" fill>
        <div ng-controller="DashboardCtrl">
            <div class="summary-overview" ng-include="'InvoiceListing/SummaryOverview' | localizedUrl"></div>            
            <twf:actions title="@Common.Invoicing">
                <twf:action target="Invoice" icon="file" active="canCreateInvoice()"><span>@Common.NewInvoice</span></twf:action>
                <twf:action target="Articles" icon="shopping-cart" active="true">@Articles.ArticlesTitle</twf:action>
                <twf:action target="Article" icon="plus-sign-alt" active="canCreateArticle()">@Articles.AddArticle</twf:action>
                <twf:action target="Customers" icon="group" active="true">@Customers.CustomersTitle</twf:action>
                <twf:action target="Customer" icon="user" active="canCreateCustomer()">@Customers.AddCustomer</twf:action>
                <twf:action target="EmailTemplate" icon="envelope" active="true">@EmailTemplate.Title</twf:action>
            </twf:actions>            
            <twf:tasks related-to="all" />    
        </div>
    </div>
</section>  
  
GET /SalesInvoicing/Client/1.18.1.2463/en/Dashboard HTTP/1.1

<section class="content-panel">
  <div class="title">Sales</div>
    <div class="fill" fill>
        <div ng-controller="DashboardCtrl">
            <div class="summary-overview" ng-include="'InvoiceListing/SummaryOverview' | localizedUrl"></div>
            <twf:actions title="Invoicing">
                <twf:action target="Invoice" icon="file" active="canCreateInvoice()"><span>New Invoice</span></twf:action>
                <twf:action target="Articles" icon="shopping-cart" active="true">Articles</twf:action>
                <twf:action target="Article" icon="plus-sign-alt" active="canCreateArticle()">Add article</twf:action>
                <twf:action target="Customers" icon="group" active="true">Customers</twf:action>
                <twf:action target="Customer" icon="user" active="canCreateCustomer()">Add customer</twf:action>
                <twf:action target="EmailTemplate" icon="envelope" active="true">Email template</twf:action>
            </twf:actions>    
            <twf:tasks related-to="all" />    
        </div>
    </div>
</section>
  
<div ng-include="'TemplateName' | localizedUrl"></div>
index.cshtml
angular.module('twinfield.settings')
      .value('uiOptions', { culture: 'en' })
      .value('userSettings', {})
      .value('companySettings', {})
      .value('templatesVersion', '1.18.1.2463')
      .value('rootPath', '/SalesInvoicing/Client/')
      .value('apiRoot', '/SalesInvoicing/api/');
http://localhost:8180/SalesInvoicing/api/
{
  "user": "Valentyn",
  "companyName": "Testing company",
  "culture": "en",...}
GET /SalesInvoicing/Client/1.18.1.2463/en/TemplateName HTTP/1.1
Cache-Control: public
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Expires: Sun, 24 Nov 2013 11:25:13 GMT
We try to obay the Standarts W3C: HTML5 RFC: HTTP
200 Ok I have info for you
204 No Content Entity updated
400 Bad Request No support
301 Moved Permanently Renamed
405 Method not allowed Can't post
201 Created Entity created
Q&A