KEMBAR78
The Full Power of ASP.NET Web API | PPTX
Browser Request
Index.html
MVC4
Traditional Request / Response for ALL rendered content and assets
Initial Request
Application.htm
MVC4
RequireJS Loader
Page1 Partial.htm
IndexViewModel.js
Application.js (bootstrap)
ViewModel (#index)
ViewModel (#login)
Model (LoginModel)
JSON Requests
HTML5 localstorage
Handling disconnection
Source: www.programmableweb.com – current APIs: 4,535
POST SimpleService.asmx/EchoString HTTP/1.1
Host: localhost:1489
User-Agent: Mozilla/5.0
Accept: text/html
Content-Type: application/json;
Content-Length: 27
...
XML, JSON, SOAP, AtomPub ...
Headers
Data
Verb URL
POST SimpleService.asmx/EchoString HTTP/1.1
Host: localhost:1489
User-Agent: Mozilla/5.0
Accept: text/html,application/xhtml+xml
Content-Type: application/json;
Content-Length: 27
...
{
"Age":37,
"FirstName":"Eyal",
"ID":"123",
"LastName":"Vardi“
}
Headers
Data
Verb URL
<Envelope>
<Header>
<!–- Headers -->
<!-- Protocol's & Polices -->
</Header>
<Body>
<!– XML Data -->
</Body>
</Envelope>
SOAP REST OData JSON POX ??
Dependency Injection
Filters
Content Negotiation
Testing
Embrace HTTP
“An architectural style for
building distributed
hypermedia systems.”
WSDL description of a web services
types defined in <xsd:schema>
simple messages
parts of messages
interface specification
operations of an interface
input message
output message
binding of interface to protocols & encoding
description of the binding for each operation
service description
URI and binding to port
<definitions>
<types></types>
<message>
<part></part>
</message>
<portType>
<operation>
<input>
<output>
</operation>
</portType>
<binding>
<operation>
</binding>
<service>
<port>
</service>
</definitions>
ASP.NET MVC 4 and the Web API: Building a REST Service from Start to Finish book
ASP.NET MVC 4 and the Web API: Building a REST Service from Start to Finish book
ASP.NET MVC 4 and the Web API: Building a REST Service from Start to Finish book
<?xml version="1.0" encoding="utf-8"?>
<Tasks>
<TaskInfo Id="1234" Status="Active" >
<link rel="self" href="/api/tasks/1234" method="GET" />
<link rel="users" href="/api/tasks/1234/users" method="GET" />
<link rel="history" href="/api/tasks/1234/history" method="GET" />
<link rel="complete" href="/api/tasks/1234" method="DELETE" />
<link rel="update" href="/api/tasks/1234" method="PUT" />
</TaskInfo>
<TaskInfo Id="0987" Status="Completed" >
<link rel="self" href="/api/tasks/0987" method="GET" />
<link rel="users" href="/api/tasks/0987/users" method="GET" />
<link rel="history" href="/api/tasks/0987/history" method="GET" />
<link rel="reopen" href="/api/tasks/0987" method="PUT" />
</TaskInfo>
</Tasks>
/api/tasks
ASP.NET MVC 4 and the Web API: Building a REST Service from Start to Finish book
ASP.NET and Web Tools 2012.2 Update
Adding a simple Test
Client to ASP.NET
Web API Help Page
Serialization Validation
DeserializationResponse
Controller /
Action
Request
HTTP/1.1 200 OK
Content-Length: 95267
Content-Type: text/html | application/json
Accept: text/html, application/xhtml+xml, application/xml
GlobalConfiguration.Configuration.Formatters
var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.UseDataContractJsonSerializer = true;
 "opt-out" approach
 "opt-in" approach
public class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
[JsonIgnore]
public int ProductCode { get; set; }
}
[DataContract] public class Product
{
[DataMember] public string Name { get; set; }
[DataMember] public decimal Price { get; set; }
// omitted by default
public int ProductCode { get; set; }
}
public object Get()
{
return new {
Name = "Alice",
Age = 23,
Pets = new List<string> { "Fido", "Polly", "Spot" } };
}
public void Post(JObject person)
{
string name = person["Name"].ToString();
int age = person["Age"].ToObject<int>();
}
var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
xml.UseXmlSerializer = true;
The XmlSerializer class supports a narrower set of types
than DataContractSerializer, but gives more control over the resulting
XML. Consider using XmlSerializer if you need to match an existing XML
schema.
“the process of selecting the best
representation for a given response when
there are multiple representations
available.”
public HttpResponseMessage GetProduct(int id)
{
var product = new Product() { Id = id, Name = "Gizmo", Price = 1.99M };
IContentNegotiator negotiator = this.Configuration
.Services.GetContentNegotiator();
ContentNegotiationResult result = negotiator.Negotiate( typeof(Product),
this.Request, this.Configuration.Formatters);
if (result == null) {
var response = new HttpResponseMessage(HttpStatusCode.NotAcceptable);
throw new HttpResponseException(response));
}
return new HttpResponseMessage()
{
Content = new ObjectContent<Product>(
product, // What we are serializing
result.Formatter, // The media formatter
result.MediaType.MediaType // The MIME type
)
};
}
public class ProductMD
{
[StringLength(50), Required]
public string Name { get; set; }
[Range(0, 9999)]
public int Weight { get; set; }
}
 [Required]
 [Exclude]
 [DataType]
 [Range]
[MetadataTypeAttribute( typeof( Employee.EmployeeMetadata ) )]
public partial class Employee
internal sealed class EmployeeMetadata
[StringLength(60)]
[RoundtripOriginal]
public string AddressLine { get; set; }
}
}
 [StringLength(60)]
 [RegularExpression]
 [AllowHtml]
 [Compare]
public class ProductsController : ApiController
{
public HttpResponseMessage Post(Product product)
{
if ( ModelState.IsValid ) {
// Do something with the product (not shown).
return new HttpResponseMessage(HttpStatusCode.OK);
}
else {
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
}
}
public class ModelValidationFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.ModelState.IsValid == false)
{
// Return the validation errors in the response body.
var errors = new Dictionary<string, IEnumerable<string>>();
foreach ( var keyValue in actionContext.ModelState )
{
errors[keyValue.Key] =
keyValue.Value.Errors.Select(e => e.ErrorMessage);
}
actionContext.Response =
actionContext
.Request
.CreateResponse(HttpStatusCode.BadRequest, errors);
}
}
}
public class ModelValidationFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.ModelState.IsValid == false)
{
// Return the validation errors in the response body.
var errors = new Dictionary<string, IEnumerable<string>>();
foreach ( var keyValue in actionContext.ModelState )
{
errors[keyValue.Key] =
keyValue.Value.Errors.Select(e => e.ErrorMessage);
}
actionContext.Response =
actionContext
.Request
.CreateResponse(HttpStatusCode.BadRequest, errors);
}
}
}
protected void Application_Start() {
// ...
GlobalConfiguration
.Configuration
.Filters.Add(new ModelValidationFilterAttribute());
}
var config = new HttpSelfHostConfiguration("http://localhost:8080");
config.Routes.MapHttpRoute(
"API Default", "api/{controller}/{id}",
new { id = RouteParameter.Optional });
using (HttpSelfHostServer server = new HttpSelfHostServer(config))
{
server.OpenAsync().Wait();
Console.ReadLine();
}
http://www.asp.net/web-api/
Why I’m giving REST a rest
Building Hypermedia Web APIs with ASP.NET Web API
eyalvardi.wordpress.com

The Full Power of ASP.NET Web API

  • 4.
    Browser Request Index.html MVC4 Traditional Request/ Response for ALL rendered content and assets
  • 5.
    Initial Request Application.htm MVC4 RequireJS Loader Page1Partial.htm IndexViewModel.js Application.js (bootstrap) ViewModel (#index) ViewModel (#login) Model (LoginModel) JSON Requests HTML5 localstorage Handling disconnection
  • 6.
  • 9.
    POST SimpleService.asmx/EchoString HTTP/1.1 Host:localhost:1489 User-Agent: Mozilla/5.0 Accept: text/html Content-Type: application/json; Content-Length: 27 ... XML, JSON, SOAP, AtomPub ... Headers Data Verb URL
  • 10.
    POST SimpleService.asmx/EchoString HTTP/1.1 Host:localhost:1489 User-Agent: Mozilla/5.0 Accept: text/html,application/xhtml+xml Content-Type: application/json; Content-Length: 27 ... { "Age":37, "FirstName":"Eyal", "ID":"123", "LastName":"Vardi“ } Headers Data Verb URL <Envelope> <Header> <!–- Headers --> <!-- Protocol's & Polices --> </Header> <Body> <!– XML Data --> </Body> </Envelope>
  • 11.
    SOAP REST ODataJSON POX ??
  • 12.
  • 13.
  • 17.
    “An architectural stylefor building distributed hypermedia systems.”
  • 18.
    WSDL description ofa web services types defined in <xsd:schema> simple messages parts of messages interface specification operations of an interface input message output message binding of interface to protocols & encoding description of the binding for each operation service description URI and binding to port <definitions> <types></types> <message> <part></part> </message> <portType> <operation> <input> <output> </operation> </portType> <binding> <operation> </binding> <service> <port> </service> </definitions>
  • 19.
    ASP.NET MVC 4and the Web API: Building a REST Service from Start to Finish book
  • 20.
    ASP.NET MVC 4and the Web API: Building a REST Service from Start to Finish book
  • 21.
    ASP.NET MVC 4and the Web API: Building a REST Service from Start to Finish book
  • 22.
    <?xml version="1.0" encoding="utf-8"?> <Tasks> <TaskInfoId="1234" Status="Active" > <link rel="self" href="/api/tasks/1234" method="GET" /> <link rel="users" href="/api/tasks/1234/users" method="GET" /> <link rel="history" href="/api/tasks/1234/history" method="GET" /> <link rel="complete" href="/api/tasks/1234" method="DELETE" /> <link rel="update" href="/api/tasks/1234" method="PUT" /> </TaskInfo> <TaskInfo Id="0987" Status="Completed" > <link rel="self" href="/api/tasks/0987" method="GET" /> <link rel="users" href="/api/tasks/0987/users" method="GET" /> <link rel="history" href="/api/tasks/0987/history" method="GET" /> <link rel="reopen" href="/api/tasks/0987" method="PUT" /> </TaskInfo> </Tasks> /api/tasks
  • 23.
    ASP.NET MVC 4and the Web API: Building a REST Service from Start to Finish book
  • 30.
    ASP.NET and WebTools 2012.2 Update Adding a simple Test Client to ASP.NET Web API Help Page
  • 33.
    Serialization Validation DeserializationResponse Controller / Action Request HTTP/1.1200 OK Content-Length: 95267 Content-Type: text/html | application/json Accept: text/html, application/xhtml+xml, application/xml
  • 34.
  • 35.
    var json =GlobalConfiguration.Configuration.Formatters.JsonFormatter; json.UseDataContractJsonSerializer = true;
  • 36.
     "opt-out" approach "opt-in" approach public class Product { public string Name { get; set; } public decimal Price { get; set; } [JsonIgnore] public int ProductCode { get; set; } } [DataContract] public class Product { [DataMember] public string Name { get; set; } [DataMember] public decimal Price { get; set; } // omitted by default public int ProductCode { get; set; } }
  • 37.
    public object Get() { returnnew { Name = "Alice", Age = 23, Pets = new List<string> { "Fido", "Polly", "Spot" } }; } public void Post(JObject person) { string name = person["Name"].ToString(); int age = person["Age"].ToObject<int>(); }
  • 38.
    var xml =GlobalConfiguration.Configuration.Formatters.XmlFormatter; xml.UseXmlSerializer = true; The XmlSerializer class supports a narrower set of types than DataContractSerializer, but gives more control over the resulting XML. Consider using XmlSerializer if you need to match an existing XML schema.
  • 41.
    “the process ofselecting the best representation for a given response when there are multiple representations available.”
  • 42.
    public HttpResponseMessage GetProduct(intid) { var product = new Product() { Id = id, Name = "Gizmo", Price = 1.99M }; IContentNegotiator negotiator = this.Configuration .Services.GetContentNegotiator(); ContentNegotiationResult result = negotiator.Negotiate( typeof(Product), this.Request, this.Configuration.Formatters); if (result == null) { var response = new HttpResponseMessage(HttpStatusCode.NotAcceptable); throw new HttpResponseException(response)); } return new HttpResponseMessage() { Content = new ObjectContent<Product>( product, // What we are serializing result.Formatter, // The media formatter result.MediaType.MediaType // The MIME type ) }; }
  • 44.
    public class ProductMD { [StringLength(50),Required] public string Name { get; set; } [Range(0, 9999)] public int Weight { get; set; } }
  • 45.
     [Required]  [Exclude] [DataType]  [Range] [MetadataTypeAttribute( typeof( Employee.EmployeeMetadata ) )] public partial class Employee internal sealed class EmployeeMetadata [StringLength(60)] [RoundtripOriginal] public string AddressLine { get; set; } } }  [StringLength(60)]  [RegularExpression]  [AllowHtml]  [Compare]
  • 46.
    public class ProductsController: ApiController { public HttpResponseMessage Post(Product product) { if ( ModelState.IsValid ) { // Do something with the product (not shown). return new HttpResponseMessage(HttpStatusCode.OK); } else { return new HttpResponseMessage(HttpStatusCode.BadRequest); } } }
  • 47.
    public class ModelValidationFilterAttribute: ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { if (actionContext.ModelState.IsValid == false) { // Return the validation errors in the response body. var errors = new Dictionary<string, IEnumerable<string>>(); foreach ( var keyValue in actionContext.ModelState ) { errors[keyValue.Key] = keyValue.Value.Errors.Select(e => e.ErrorMessage); } actionContext.Response = actionContext .Request .CreateResponse(HttpStatusCode.BadRequest, errors); } } }
  • 48.
    public class ModelValidationFilterAttribute: ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { if (actionContext.ModelState.IsValid == false) { // Return the validation errors in the response body. var errors = new Dictionary<string, IEnumerable<string>>(); foreach ( var keyValue in actionContext.ModelState ) { errors[keyValue.Key] = keyValue.Value.Errors.Select(e => e.ErrorMessage); } actionContext.Response = actionContext .Request .CreateResponse(HttpStatusCode.BadRequest, errors); } } } protected void Application_Start() { // ... GlobalConfiguration .Configuration .Filters.Add(new ModelValidationFilterAttribute()); }
  • 52.
    var config =new HttpSelfHostConfiguration("http://localhost:8080"); config.Routes.MapHttpRoute( "API Default", "api/{controller}/{id}", new { id = RouteParameter.Optional }); using (HttpSelfHostServer server = new HttpSelfHostServer(config)) { server.OpenAsync().Wait(); Console.ReadLine(); }
  • 56.
    http://www.asp.net/web-api/ Why I’m givingREST a rest Building Hypermedia Web APIs with ASP.NET Web API
  • 58.

Editor's Notes

  • #3 OSScreen ResolutionDeploymentSecurityBrowsersLoad Balance
  • #14 Use HTTP as an Application Protocol – not a Transport Protocol
  • #46 [ExternalReference] [Association(&quot;Sales_Customer&quot;, &quot;CustomerID&quot;, &quot;CustomerID&quot;)]