Create mobile apps with HTML5, JavaScript and Visual Studio

(Elle) #1

8 msdn magazine Cutting Edge


Note that this is the same code you’d use to add a Web API con-


troller to an ASP.NET MVC application. You also have to specify


routes. Here’s some code you want to run at application startup:


RouteTable.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = System.Web.Http.RouteParameter.Optional });

Unless otherwise annotated with the NonAction attribute, any


public methods on the class that match the default naming and


routing conventions are public HTTP-callable endpoints. Th ey


can be called from any client without the need for generated proxy


classes, web.confi g references or special code.


Routing conventions in Web API dictate the URL starts with /api


followed by the controller name. Note that there’s no action name


clearly expressed. Th e action is determined by the type of request,


whether GET, PUT, POST or DELETE. A method name that begins


with Get, Put, Post or Delete is conventionally mapped to the corre-


sponding action. For example, a method GetTasks on a TaskController


will be invoked for any GET request to a URL such as /api/task.


Regardless of the apparent similarity of behavior and class


names with ASP.NET MVC, Web API lives in a completely


separate set of assemblies and uses a completely diff erent set of


types—System.Net.Http is the primary assembly.


Inside Web API Content Negotiation


“Content negotiation” is often used to describe the process of


inspecting the structure of an incoming HTTP request to fi gure


out the formats in which the client wishes to receive responses.


Technically, though, content negotiation is the process in which


client and server determine the best possible representation format


to use in their interactions. Inspecting the request typically means


looking into a couple of HTTP headers such as Accept and


Content-Type. Content-Type, in particular, is used on the


server for processing POST and PUT requests and on the client


for choosing the formatter for HTTP responses. Content-Type is


not used for GET requests.


The internal machinery of content negotiation, however, is


much more sophisticated. Th e aforementioned scenario is the most


typical—because of default conventions and implementations—


but it isn’t the only one possible.


Th e component that governs the negotiation process in Web


API is the class called DefaultContentNegotiator. It implements a


public interface (IContentNegotiator), so you can replace it entirely


if needed. Internally, the default negotiator applies several distinct


criteria in order to fi gure out the ideal format for the response.


The negotiator works with a list of registered media type


formatters—the components that actually turn objects into a specifi c


format. Th e negotiator goes through the list of formatters and stops at


the fi rst match. A formatter has a couple of ways to let the negotiator


know it can serialize the response for the current request.


Th e fi rst check occurs on the content of the MediaTypeMappings


collection, which is empty by default in all predefi ned media type


formatters. A media type mapping indicates a condition that, if


verified, entitles the formatter to serialize the response for the


ongoing request. Th ere are a few predefi ned media type mappings.


One looks at a particular parameter in the query string. For exam-


ple, you can enable XML serialization by simply requiring that an


xml=true expression is added to the query string used to invoke


Web API. For this to happen, you need to have the following code


in the constructor of your custom XML media type formatter:


MediaTypeMappings.Add(new QueryStringMapping("xml", "true", "text/xml"));

In a similar way, you can have callers express their preferences by


adding an extension to the URL or by adding a custom HTTP header:


MediaTypeMappings.Add(new UriPathExtensionMapping("xml", "text/xml"));
MediaTypeMappings.Add(new RequestHeaderMapping("xml", "true",
StringComparison.InvariantCultureIgnoreCase, false,"text/xml"));

For URL path extension, it means the following URL will map


to the XML formatter:


http://server/api/news.xml

Note that for URL path extensions to work you need to have an


ad hoc route such as:


config.Routes.MapHttpRoute(
name: "Url extension",
routeTemplate: "api/{controller}/{action}.{ext}/{id}",
defaults: new { id = RouteParameter.Optional }
);

For custom HTTP headers, the constructor of the Request-


HeaderMapping class accepts the name of the header, its expected


value and a couple of extra parameters. One optional parameter


indicates the desired string comparison mode, and the other is a


Boolean that indicates if the comparison is on the entire string. If


the negotiator can’t fi nd a match on the formatter using the media


type mapping information, it looks at standard HTTP headers such


as Accept and Content-Type. If no match is found, it again goes


through the list of registered formatters and checks whether the


return type of the request can be serialized by one of the formatters.


To add a custom formatter, insert something like the follow-


ing code in the startup of the application (for example, in the


Application_Start method):


config.Formatters.Add(xmlIndex, new NewsXmlFormatter());

Customizing the Negotiation Process


Most of the time, media type mappings let you easily fulfi ll any


special requirements for serialization. However, you can always


replace the default content negotiator by writing a derived class


and overriding the MatchRequestMediaType method:


protected override MediaTypeFormatterMatch MatchRequestMediaType(
HttpRequestMessage request, MediaTypeFormatter formatter)
{
...
}

You can create a completely custom content negotiator with a new


class that implements the IContentNegotiator interface. Once you


have a handmade negotiator, you register it with the Web API runtime:


GlobalConfiguration.Configuration.Services.Replace(
typeof(IContentNegotiator),
new YourOwnNegotiator());

Th e preceding code usually goes in global.asax or in one of those


handy config handlers that Visual Studio creates for you in the


ASP.NET MVC Web API project template.


Controlling Content Formatting from the Client


Th e most common scenario for content negotiation in Web API


is when the Accept header is used. Th is approach makes content


formatting completely transparent to your Web API code. Th e caller


sets the Accept header appropriately (for example, to text/xml) and


the Web API infrastructure handles it accordingly. Th e following

Free download pdf