Hypermedia-REST-APIs
mit der ASP.NET Web API und OData



Navigation mit Esc, und
![johannes](images/johannes.png) ### [Johannes Hoppe](http://JohannesHoppe.de)
# RESTful ![tools](images/icon_communication.png)
## Level 0: Pox Richardson Maturity Model
## Level 0: Pox ```html contenteditable HTTP/1.1 200 OK Content-Type: application/soap+xml; charset=utf-8 _LT_?xml version="1.0"?_GT_ _LT_soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"_GT_ _LT_soap:Body xmlns:m="http://www.example.org/stock"_GT_ _LT_m:GetStockPriceResponse_GT_ _LT_m:Price_GT_34.5_LT_/m:Price_GT_ _LT_/m:GetStockPriceResponse_GT_ _LT_/soap:Body_GT_ _LT_/soap:Envelope_GT_ ```
## Level 1: Uri
## Level 1: Uri ```cmd contenteditable GET /Home/GetAllNotes?limit=200_AMP_search=test ```
## Level 2: http verbs & status codes
## Level 2: http verbs & status codes ```txt contenteditable GET PUT POST DELETE ```
## Level 3: hypermedia Hypermedia As The Engine Of Application State

?

## ja, und nun?
* Protokolle, Formate & Konventionen * [Collection+JSON](http://amundsen.com/media-types/collection/), [HAL](http://stateless.co/hal_specification.html), [JSON-Home](http://tools.ietf.org/html/draft-nottingham-json-home-03), [JSON-LD](http://json-ld.org/), ...
### Microsofts Antwort:
### Demo Die "Geschäftslogik": DTOs + Entity Framework 6
```javascript small contenteditable public class Customer { public Customer() { Invoices = new List_LT_Invoice_GT_(); } public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public DateTime DateOfBirth { get; set; } public virtual ICollection_LT_Invoice_GT_ Invoices { get; set; } } public class Invoice { public int Id { get; set; } public decimal Amount { get; set; } public int CustomerId { get; set; } public virtual Customer Customer { get; set; } } public class DataContext : DbContext { public DbSet_LT_Customer_GT_ Customers { get; set; } public DbSet_LT_Invoice_GT_ Invoices { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new InvoiceMap()); } } ```
#### Daten per Web API anbieten Klickibunti CRUD ![Abbildung 1](images/image01_scaffolding_B.png)
### Los geht's!
```cmd GET http://example.org/api/Customers ```
```javascript contenteditable define(['angular'], function(angular) { return angular.module('listing1', []) .controller('listing1Controller', [ '$scope', '$http', function($scope, $http) { $scope.customers = []; $http.get('/api/Customers').success(function(data) { $scope.customers = data; }); } ]); }); ```
## Laaaangsam! Warum dauert das so lang?! ![Abbildung 2](images/image02_bootstrap_tabelle.png)
## 2. Versuch ``` javascript small contenteditable public class CustomersController : ODataController { private DataContext db = new DataContext(); // GET: odata/Customers [EnableQuery] public IQueryable_LT_Customer_GT_ GetCustomers() { return db.Customers; } /* [...] */ } ``` ``` javascript small contenteditable public static class WebApiConfig { public static void Register(HttpConfiguration config) { ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.EntitySet_LT_Customer_GT_("Customers"); builder.EntitySet_LT_Invoice_GT_("Invoices"); config.Routes.MapODataServiceRoute("odata", "odata", builder.GetEdmModel()); } } ```
### [URL Conventions](http://www.odata.org/documentation/odata-version-3-0/url-conventions/)
```cmd GET http://example.org/odata/Customers?$top=5_AMP_$skip=2 ``` * Paging: /odata/Customers?$top=5&$skip=2 * Paging mit Count: /odata/Customers?$top=5&$skip=2&$inlinecount=allpages * Filtern: /odata/Customers?$filter=FirstName eq 'Hans'
### Metadaten in OData
```cmd GET http://example.org/odata/$metadata ```
### 3rd-party controls [Kendo UI Grid](http://demos.telerik.com/kendo-ui/grid/index) [![Abbildung 3](images/image03_kendo_ui_grid.png)](http://demos.telerik.com/kendo-ui/grid/index)
### 3rd-party controls [BreezeJS](http://learn.breezejs.com/) ``` javascript small var manager = new breeze.EntityManager('/odata'); new breeze.EntityQuery() .using(manager) .from("Customers") .orderBy("FirstName") .where("FirstName", "eq", "Jack") .execute() .then(function(data) { $scope.customers = data.results; }); ```
### [OData Explorer](http://pragmatiqa.com/xodata/) [![screenshot](images/screenshot-explorer.png)](http://pragmatiqa.com/xodata/)
## Mitnehmen! Artikel mit Details auf 8 prallen A4-Seiten [Artikel PDF](http://johanneshoppe.github.io/Presentations2015/Rest-WebAPI-OData/Doc/Hypermedia-REST-APIs%20mit%20der%20ASP.NET%20Web%20API%20und%20OData.pdf) | [Artikel Online](https://github.com/JohannesHoppe/Presentations2015/blob/gh-pages/Rest-WebAPI-OData/Doc/index.md)
## Downloads ![tools](images/icon_file.png) #### [github.com/JohannesHoppe/Presentations2015](https://github.com/JohannesHoppe/Presentations2015/)
# Danke!
*  [johanneshoppe.de](http://johanneshoppe.de) *  [@JohannesHoppe](https://twitter.com/JohannesHoppe) *  [Johannes.Hoppe](https://www.facebook.com/johannes.hoppe)

Created by Johannes Hoppe | Print PDF