Saturday, 28 April 2012

ASP.NET Web API Series - Part 5: MediaTypeFormatter explained


Introduction

[Level T2] MediaTypeFormatter is an exciting concept introduced in the ASP.NET Web API which will enable seamless conversion of HTTP data to/from.NET types. This post reviews the concepts and basic usage of MediaTypeFormatter in the ASP.NET Web API pipeline. This is an area of Web API which is being actively developed so the content of this post might be updated to reflect the changes - but this post at the time of publishing is based on the latest source code available.

Background

HTTP abstracts a resource (identified by a URI which is commonly a URL) from its representation. A resource e.g. an employee detail can be identified by /employees/123. An HTTP agent (client) and a server engage in content negotiation to decide on the best format it can be represented. For example, a client can express its wishes to receive employee detail in plain text (by specifying content-type header of text/plain), RTF, XML, JSON or even image.

On the other hand, ASP.NET Web API has also abstracted away parameters or result of an action form its representation. While ASP.NET MVC had this feature for input parameters, return type should have been an instance of ActionResult hence controller had to make a decision on the format of resource by returning ContentResult, JsonResult, etc.

MediaTypeFormatter as we will see will bridge the gap between these two abstractions.

What is Media Type?

As you all probably know, media type refers to the value of the content-type header within an HTTP request and response. Media types allow agent (client) and server to define the type of the data sent in the HTTP body (payload). It is also used within the accept header in the request to allow content negotiation, i.e. client notifies the server of the media types it accepts/prefers. I will need to have a separate post on content negotiation but as for now, this little introduction suffices.

There are standard media types as listed in the Wiki link. There is no limitation on the media types and you can come up with your own media types but these media types usually start with X-.

A request or response does not have to have a single media type. It can mix the media types but in this case it has to use multipart content-type (value of the content type will be multipart/mixed) so that each part defines its content type.

What is MediaTypeFormatter?

Media type formatter is the bridge between the HTTP world of URI fragments, headers and body on one side, and the controller world of actions, parameters and return types.

Tower Bridge of Web API
Tower Bridge of ASP.NET Web API

A media type formatter in brief:
  1. Has a knowledge of one or more media type (for example text/xml and application/xml both refer to the same structure which is XML) and tells Web API which content types it supports (for the HTTP world)
  2. Tells Web API whether it can read or write a type (for Controller world)
  3. Has an understanding of encoding/charset which is passed in the HTTP header and can read accordingly
  4. It will be given a stream to read (from request) or write (to response)
  5. Its work usually (but not always) involves serialisation (at the time writing to the response) or deserialisation (at the time of reading from the request)
  6. Inherits abstract class MediaTypeFormatter

MediaTypeFormatter class

MediaTypeFormatter class in the ASP.NET Web API is an abstract class providing base services for various media type formatters.

Important properties and methods include (more informative as code):

public abstract class MediaTypeFormatter
{

 // properties
 public Collection<MediaTypeHeaderValue> SupportedMediaTypes { get; private set; }
 
 public Collection<Encoding> SupportedEncodings { get; private set; }
 
 public Collection<MediaTypeMapping> MediaTypeMappings { get; private set; }
 
 // methods
 public virtual Task<object> ReadFromStreamAsync(Type type, Stream stream, HttpContentHeaders contentHeaders, IFormatterLogger formatterLogger)
 {
  // to be overriden by base class
 }

 public virtual Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, TransportContext transportContext)
 {
  // to be overriden by base class
  }

 public abstract bool CanReadType(Type type);

 public abstract bool CanWriteType(Type type);

}


Things to note above are:

  • As with the rest of the Web API, MediaTypeFormatter fully supports Async using TPL. Having said that, most implementations of  MediaTypeFormatter run synchronously as they involve serialisation which is safe as a synchronous operation. 
  • SupportedMediaTypes defines a list of media type headers that an implementation supports. For example application/xml and text/xml
  • MediaTypeMappings is an interesting concept where a media type formatter can define its preference for a particular media type based on a value in the request (query string, URI fragment, HTTP header). A typical example is existence of x-requested-with header which signals the AJAX based request hence JSON is the preferred content-type.

How ASP.NET Web API uses formatters?

Media type formatters are global formatters sitting in the Formatters property of HttpConfiguration. If you are using ASP.NET hosting (IIS, Cassini, etc) then you may use GlobalConfiguration.Configuration to access the instance of HttpConfiguration containing Formatters. If you are using Self-Hosting, then you would be creating a HttpSelfHostConfiguration object which you will use its Formatters property.

This snippet will output all formatters that are setup by default in the ASP.NET Web API:

foreach (var formatter in config.Formatters)
{
 Trace.WriteLine(string.Format("{0}: {1}", 
  formatter.GetType().Name,
  string.Join(", ", formatter.SupportedMediaTypes.Select(x=>x.MediaType))
  ));
}

And here is the output (at the time of writing this blog):

JsonMediaTypeFormatter: application/json, text/json
XmlMediaTypeFormatter: application/xml, text/xml
FormUrlEncodedMediaTypeFormatter: application/x-www-form-urlencoded
JQueryMvcFormUrlEncodedFormatter: application/x-www-form-urlencoded
This list is very much likely to be extended by the time ASP.NET Web API is shipped. 

You might be surprised to see two different media type formatters targeting the same media type. But that is very normal: media type formatters compete for becoming the formatter of choice! If ASP.NET Web API find two formatters for the same content type, it will pick the first one so it is very important to add formatters in the right order.

Writing a simple BinaryMediaTypeFormatter

Now, we want to get our hands dirty and implement a useful formatter that is not currently provided by the ASP.NET Web API. This formatter will be able to formatter application/octet-stream media type in the HTTP world to the byte[] type in the controller world.

Let's imagine we have a controller that calculates SHA1 hash of the small binary data posted to it (this is a good practice for large streams):

public class BinaryController : ApiController
{
 [HttpPost]
 public string CalculateHash(byte[] data)
 {
  using(var sha1 = new SHA1CryptoServiceProvider())
  {
   return Convert.ToBase64String(sha1.ComputeHash(data));       
  }
 }
}

In our implementation, we use synchronous approach, although in this case it is safe to use asynchronous as there is no serialisation taking place. However, since this is intended only for small payloads, context switching of the asynchronous TPL has more overhead - in any case turning this code into asynchronous is very easy: an alternate implementation supporting async can be found here.


public class BinaryMediaTypeFormatter : MediaTypeFormatter
{

 private static Type _supportedType = typeof (byte[]);
 private const int BufferSize = 8192; // 8K 

 public BinaryMediaTypeFormatter()
 {
  SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/octet-stream"));
 }

 public override bool CanReadType(Type type)
 {
  return type == _supportedType;
 }

 public override bool CanWriteType(Type type)
 {
  return type == _supportedType;
 }

 public override Task<object> ReadFromStreamAsync(Type type, Stream stream, 
  HttpContentHeaders contentHeaders, IFormatterLogger formatterLogger)
 {
  var taskSource = new TaskCompletionSource<object>();
  try
  {
   var ms = new MemoryStream();
   stream.CopyTo(ms, BufferSize);
   taskSource.SetResult(ms.ToArray());
  }
  catch (Exception e)
  {
   taskSource.SetException(e);
  }
  return taskSource.Task;
 }

 public override Task WriteToStreamAsync(Type type, object value, Stream stream, 
  HttpContentHeaders contentHeaders, TransportContext transportContext)
 {
  var taskSource = new TaskCompletionSource<object>();
  try
  {
   if (value == null)
    value = new byte[0];
   var ms = new MemoryStream((byte[]) value);
   ms.CopyTo(stream);
   taskSource.SetResult(null);
  }
  catch (Exception e)
  {
   taskSource.SetException(e);
  }
  return taskSource.Task;
 }
}

Using BinaryMediaTypeFormatter

Now let's use our formatter. You need a REST console of your choice (Chrome REST console, REST Sharp library, Fiddler) to send this request:

POST http://localhost:7777/api/Binary HTTP/1.1
User-Agent: Fiddler
Host: localhost:7777
content-type: application/octet-stream
Content-Length: 14

This is a test

Since we have not yet added our formatter, we get back this error:
No MediaTypeFormatter is available to read an object of type 'Byte[]' from content with media type 'application/octet-stream'.
So we just need to add our formatter:

config.Formatters.Add(new BinaryMediaTypeFormatter());

And we will get back this response:

HTTP/1.1 200 OK
Content-Length: 30
Content-Type: application/json; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Date: Sat, 28 Apr 2012 12:09:44 GMT

"pU2I4GYS2CC8O+cod8dPJXtWGxk="
As you can see, the response content type is application/json. I have explained in my post Part 1 why it is the case: JsonMediaTypeFormatter is the default media type formatter. Now we know why it is the case: it is the first item in the collection (see above).

Conclusion

Media type formatter is the bridge between the HTTP world of URI, headers and body on one side, and the controller world of actions, parameters and return types. In ASP.NET Web API, it is represented by abstract class MediaTypeFormatter. Order of formatters in the Formatters property of HttpConfiguration is important when ASP.NET Web API has to choose between two formatters supporting the same media type.

Sunday, 22 April 2012

ASP.NET Web API Series - Part 4: Dependency Injection

[Level T2]

In this post, I will review the dependency injection features of the ASP.NET Web API. There are a few posts out there but I felt there are areas still not covered so I am exploring the dependency injection options. I do not try explaining what Dependency Injection (DI), Inversion of Control (IoC) or Service Location are. If you are not familiar with these you perhaps first need to get a grasp by reading numerous resources out there.

Until ASP.NET MVC 3 none of the Microsoft products had any IoC interoperability. In ASP.NET MVC 2 you had to resort to replacing default controller factory with your own and server controllers by using service location. In WCF you had to provide your own factories using code or config which were not great. But ASP.NET MVC 3 for the first time relinquish its hold on object creation and acknowledged the need for DI as more teams embraced it.

ASP.NET Web API beta has a built in support for dependency injection. Just be careful that there are breaking changes in the ASP.NET Web API source code and the model has changed (it has been simplified). I will shortly explain beta release and then move on to the source code which the final release will probably look more like it.

ASP.NET Web API beta release

[Remember, this stuff has changed] DI is based on setting a dependency resolver (technically a service locator) on the HttpConfiguration object. This object is on the GlobalConfiguration object as a static property (web hosting) or in case of self hosting on HttpSelfHostConfiguration.

So in case of web hosting you would use:
GlobalConfiguration.Configuration.ServiceResolver.SetResolver(myResolver);
There are basically 3 options when it comes to registering a dependency resolver:

  1. An instance of an object implementing IDependencyResolver dependency which has two methods: GetService and GetServices
  2. An instance of an object which has these two public methods: GetInstance and GetAllInstances. No interface needed and Web API will use reflection to call methods.
  3. Passing two delegates that return an instance or instances for a particular type

ASP.NET Web API source code release

This has been simplified and unified so there is only one option: using IDependencyResolver

There is one change in IDependencyResolver though: in addition to GetServeice and GetServices (which now is in IDependencyScope interface implemented by IDependencyResolver), there is a BeginScope method. 

BeginScope according to documentation is:

Starts a resolution scope. Objects which are resolved in the given scope will belong to that scope, and when the scope is disposed, those objects are returned to the container. Implementers should return a new instance of IDependencyScope every time this method is called, unless the container does not have any concept of scope or resource release (in which case, it would be okay to return 'this', so long as the calls to are effectively NOOPs).
This is particularly important if you leave responsibility of lifetime management of your objects to your DI container.


Developing a simple Dependency Resolver for AutoFac


AutoFac is my DI framework of choice (I have used Windsor and Unity before). So here I will write a few lines of code to hook AutoFac into ASP.NET Web API.

All you need to do is to implement IDependencyResolver and then create an instance of your object and use SetResolver on the configuration (see above) instance.

Your Dependency Resolver is not supposed to throw exceptions but it can return null in case the type is not registered.

ASP.NET Web API also tries to use Dependency Resolver (and in case you have provided your own will use yours) to resolve its own dependencies. This could have placed a big burden on such a dependency resolver to have knowledge of all ASP.NET Web API dependencies but the implementation is as such that Web API will use the objects that you return for dependency resolution and if you return null, it will use the default.

So here is the code for the simple AutoFac dependency resolver:
public class AutoFacDependencyResolver : IDependencyResolver
{
 private ContainerBuilder _builder = new ContainerBuilder();
 private IContainer _container;

 public ContainerBuilder Builder
 {
  get
  {
   return _builder;
  }
 }

 public void Build()
 {
  _container = _builder.Build();
 }

 public IDependencyScope BeginScope()
 {
  return this;
 }

 public object GetService(Type serviceType)
 {
  object resolved = null;
  if (_container.TryResolve(serviceType, out resolved))
   return resolved;
  else
   return null;
 }

 public IEnumerable<object> GetServices(Type serviceType)
 {
  object resolved = false;
  Type all = typeof(IEnumerable<>).MakeGenericType(serviceType);
  if (_container.TryResolve(all, out resolved))
   return (IEnumerable<object>)resolved;
  else
   return null;

 }

 public void Dispose()
 {
  if(_container!=null)
  _container.Dispose();
 }
}
Things to note are:

  • We expose the builder so the client can register the components.
  • We expose Build() method so at the end of registration, Build() is called. Ideally we should hide the builder and expose it through AutoFactDependencyResolver methods so that build could not be directly called on the builder by the client.
  • AutoFac inherently does not have a ResolveAll method but instead you may resolve IEnumerable<T> in which case works as ResolveAll.
  • Please note that we had to use TryResolve so that no exception is thrown. Alternatively you may use a try/catch block and return null in the catch (but that could mask other exceptions)  
OK, let's imagine we have a controller which is dependent on loggers:

public interface ILogger
{
 void Log(string value);
}

public class TraceLogger : ILogger
{
 public void Log(string value)
 {
  Trace.WriteLine(value);
 }
}

public class DebugLogger : ILogger
{
 public void Log(string value)
 {
  Debug.WriteLine(value);
 }
}

public class DiTestController : ApiController
{
 private ILogger _logger;
 private List<Ilogger> _loggers;

 public DiTestController(IEnumerable<Ilogger> loggers)
 {
  _loggers = loggers.ToList();
 }

 public string Get()
 {
  _loggers.ForEach(x => x.Log("Get"));
  return "Dependency Injection";
 }

}

So the controller will use ForEach to call Log on all ILoggers passed to it. In order to register the Dependency Resolver, all we have to do is this:
AutoFacDependencyResolver resolver = new AutoFacDependencyResolver();
resolver.Builder.RegisterType<TraceLogger>().As<ILogger>();
resolver.Builder.RegisterType<DebugLogger>().As<ILogger>();
resolver.Builder.RegisterType<DiTestController>();
resolver.Build();
config.DependencyResolver = resolver;

Config object here is a reference to GlobalConfiguration.Configuration (in case of web hosting) or an instance of HttpSelfHostConfiguration (in case of self-hosting).

Conclusion

Dependency injection has gone through breaking changes from ASP.NET Web API beta to the source code release. Registering your own dependency injection provider is easy and all you need is to implement IDependencyResolver and then use SetResolver method on the HttpConfiguration (depending on your hosting scenario) to register it. ASP.NET Web API will optionally try using your resolver to resolve its own dependencies but you do not have to register the defaults. Be careful to catch any dependency resolution error.



Saturday, 21 April 2012

Web API Governance - Life in a schemaless world (Take 2)

Introduction

[Level C4] While classic web services used WSDL for their schema and description, emerging Web API mainly relies on documentation. This requires human effort and with the rising popularity of Web API it could create problems in maintenance, change management and extension of Web APIs. The solution is automation and this article reviews challenges and possible solutions.

Rise of the Web API


NOTE: This is take 2 of my post, with some updates.

I am very excited at the moment. Microsoft has just released its beta version of its best HTTP implementation to date. ASP.NET Web API has embraced HTTP exposing its full goodness. No more clutter of SOAP-based RPC services. Lean and mean.

So life cannot be any better? Hmmm.. it can! Away from all the hustle and bustle and buzz of the REST APIs (whether they are really RESTful is another discussion which to be frank I am not interested any more), it is important to be objective and almost clinical about the technology. It is important to be able to look back, and see how far we have come so far and yet learn lessons from the past and use the solutions of the previous generation if they are still relevant (in IT terms it is 5-10 years depending on the technology).

There has been a movement in the industry to question the basics. This is good, it weeds out unnecessary abstractions. We have had RDBMS for years now we want NoSQL. We have had XML/SOAP now we want JSON. We have had complex layered server side architecture now we want close to the metal, like node.js or sinatra/nancyfx. Scripting was bad, type safety was good and now scripting is good and everyone wants to escape type safety.

OK, we have had SOAP services and we have never been happy with them. They were clunky, heavy and complex. Now we got Web API which is so much better. But let's have a look at the problems that classic Web Services started tackling and in fact, did a good job in some cases.

Governance in Web Services

This is an SOA term that revolved around managing and organising web services in a consistent fashion. This  would protect the clients as well as allowing the vendors to manage the life of the services. 

Some of the aspects of Governance include:
  1. Contract and description: mainly through WSDL
  2. Registry service and discovery: mainly through UDDI and later WS-Discovery
  3. Versioning
  4. Exception handling
  5. Security and access control: mainly through Web Service Extensions and later WS-Security
To be fair, the work in the area produced some useful technologies and standards. One problem being they are mainly based on the RPC style web services as such not quite useful in the REST style Web API. The issue is problems do still exist and question is whether we do have appropriate tools to address them.

What did we lose on the way?

OK, I am trying to imagine 3 years from now - I am sorry but I see chaos. A good proportion of existing Web Services will be moved to pure HTTP Web APIs. I think it is very likely that the RPC mentality stays with the developers and we end up with RPC style Web APIs. And now what? We are even more vulnerable with no classic Governance safety net.

With classic web services (and WCF), all you needed to point to a web service was its WSDL. It would provide the contract, schemata, faults, security requirements, endpoint addresses and some description. If you would update your service, the WSDL (which it could be generated on the fly) would be updated. In fact in most cases all you needed was the service endpoint address, from where you could get all informations you needed (e.g. by just placing ?wsdl at the end of the address).

We do have some replacements here in HTTP APIs. For example, we do not need SOAP fault to be defined in the WSDL, since we have HTTP error codes. We do not necessarily need WS-Security as we have OAuth/OpenID/etc token based federated security. Discovery is not really a big issue and hypermedia can help in this regard. 

OK, the question is do we need all that stuff? REST (and HTTP as its sole implementation) is Turing-complete. An agent should not need any priori knowledge to be able to use a service. It can use OPTIONS to discover verbs, it can use content-negotiation to ask for media types it can understand and use hypermedia to navigate through the resources of a server.

Turing-completeness is great but to be honest, it still belongs to Sci-Fi novels. We are not there yet. I believe for great development experience and maintenance, we still need schema. Most web APIs are about interacting with data. Probably somewhere around 80-90% of Web APIs out there serve JSON. What does application/json content type exactly tell about the actual JSON being served? Are we currently writing agents/applications that can intelligently adapt and consume whatever JSON being served to them? 

I was listening to one of the episodes of MashThis podcast and the theme that was coming on good Web API was always good documentation. Nothing beats a good documentation but how many of us developers are good in this? Human effort to create and maintain a good documentation covering schema and description is going to be big. I think we need some automation here.


Challenges

I originally suggested using media types so that client could request not the data but the schema of the data. In this update, I am going to look at other options as well as semantic challenges for providing schema and description. In fact, I am not going to propose a solution, I will use this post to describe the problem. I hope this will start a fruitful discussion so please feel free to join in.

HTTP and schema?

Schema for an HTTP API (intentionally not using the word REST API) might initially seem a little bit odd. Actually the word does not appear at all in the RFC 2616. As far as the HTTP is concerned, server will allow the agent to interact with the resource using URI using the verb and associated headers. It is up to the agent to engage in content negotiation and interpret the result.

I personally think the problem of schema and description is inherently orthogonal to HTTP. A resource does not necessarily have to have a schema - other than the schema assumed by the content-type. For example, when a server responds to a GET request for an XML page using /foo/api/2 URL, it just serves the page which ideally is conformant to XML schema. But even well-formed XML does not explain enough about the structure of the document and its internal schema. In fact XML instance will contain its schema but server (unlike RPC style web services) might not able to return an XML schema - since /foo/api/3 might have a completely different schema.

But let's bear in mind this can simply be an option. Server might support the schema/description and return, or it can return a 404 error. In fact, schema can be service-specific or URI specific, i.e. it could refer to /foo/api/{id} or /foo/api/690. In this case, while schema is relevant for different ids (as they have different schema), service description will be the same. Hence any solution must consider this variability.

URIs and URIs routing formats

It is very common in the Web API space to provide URIs containing placeholders to pass data fragments to the API. In our example, /foo/api/690 means id=690. Alternatively, data could be sent as query string parameter such as /foo/api?id=690.

The schema or description could be different based on the parameters passed.

One issue to be considered is that it is possible agent does not know about an actual existing resource (for example does not know a valid id to be passed to return an actual resource) and all it knows is the URI format. Solution must be flexible enough to provide a schema for the API method if a generic schema exist for the URI format (i.e. all documents at /foo/api/{id} have similar schema)

Priori knowledge

One of the main focuses of HTTP spec is to remove the requirement of the priori knowledge from the agents. Agent is encouraged to explore server resources and functionality (e.g. OPTIONS) and server guides the agent using hypermedia.

With developing Web API that requires documentation, we are adding back this priori knowledge requirement. This is not good. But in the absence of a standard we will end up with nothing much better than a convention - which itself is a priori knowledge. So ideally this process must involve a standard or even a standard proposal. A lot of useful technologies out in the cloud are still in the proposal phase, namely OData, JSON Schema and HAL.

Security

A schema must ideally provide a detail on the security requirements of the service. This is especially important for authentication schemes supported by the server (e.g. basic authentication, federated identiy, etc).

Schem and description as a single resource?

Decision needs to be taken to whether serve description and schema of the service separately or provide them as a single document. The more I think about it, the more I feel it probably has to be a single document.

Possible Solutions


1- Using content type

Since JSON and XML are two most popular formats being served, for now serving schema can practically be limited to these media types.

Let's Look at this request:
GET http://localhost:50459/api/HelloWorld/1.1
User-Agent: Fiddler
Host: localhost:50459
And response is:
HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Tue, 17 Apr 2012 21:46:38 GMT
Content-Type: application/json; charset=utf-8
Connection: Close 
"This"
So as we can see, media type returned is JSON and the value is a simple string. Now if we send a request asking for a JSON schema with accept header of  application/schema+json, we get back this:

GET http://localhost:50459/api/HelloWorld/1.1
Accept: application/schema+json
Host: localhost:50459 
And response is:
HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Tue, 17 Apr 2012 21:46:38 GMT
Content-Type: application/schema+json; charset=utf-8
Connection: Close 
{
  "type": "string"
It is true that JSON schema is still in draft status but with this format becoming more and more popular, it is inevitable that we restore some structure in our Web API.

Since XML already has an established schema language, we can use XML Schema but one problem is that XML Schema has a content type of application/xml or text/xml. So either we nominate an alternative content type (such as application/schema+xml) or use URI to denote request for schema (ideally in the format of optional query string parameter although that will still be part of the URI).

Same applies to the description of the service. It is ideal that the documentation of the service id provided by the service itself. For description, agent can use a special content type (for example x-text/docs) or using a query string parameter.

2- Using hypermedia

Server can include separate links to schema and description while serving the actual resource. Payload can be HAL or alternative implementations of hypermedia.

A HAL payload can look something like:

{
  "_links": {
    "description": { "href": "/description" },
    "schema": { "href": "../../schema?type=MyDto" }}
  },
  "_embedded": {
    "MyDto": [
...

Server could have an implementation convention to treat description and schema URL fragments as special paths and serve appropriate resources. Please note that all the data needed to provide the schema could be located in the URL, e.g. type of the serialised payload is appended as a query string parameter so the server does not even have to know about the API method queried about.

This imposes a burden on the agent to understand such complex structures.

Also bear in mind, an ideal solution must be able to explain the output schema as well as input schema. For POST and PUT verbs, a JSON payload could be sent to the server to be stored and server must be able to provide not only the output but also input schema.

3- Using a URL convention

Basically in this solution, agent has a priori knowledge of a convention (or a standard) by which can interrogate the server and ask for schema and description of the services available on the API server. For example /foo/api/$list could provide a list of methods (I know, it sounds like RPC but I have no better word) avilable on the server. $schema can provide the schema and $description the description for the service.

Conclusion

Web API needs to look back and consider solving some of the problems solved by classic Web Services. It is very likely that with the migration of classic web services to Web API we find ourselves in a chaotic situation. This area needs to be explored and all options to be considered hence a debate on the subject is welcome. It is likely that we might need a convention/standard for describing our Web APIs.

Sunday, 15 April 2012

ASP.NET Web API Series - Part 3: Async Deep Dive

[Level T4]

OK, in this post we will have a look at the internals of ASP.NET Web API and its async implementation. [For a newer related post see here]

As covered some ground in our previous post, we will continue our journey while this time we will have a look at the async used in the Web API Source Code was that was released recently. For more information about building and using the source code, please see my earlier post.

First some myth-busting and de-mystifying.

What exactly is Task<T>

If you start browsing through the source code of the ASP.NET Web API, you will find very few classes where they do not have xxxAsync() method or do not contain methods returning varieties of Task<T> (which from here on, I am gonna use to generically refer to all tasks including all variations such as Task and Task<T>).

Task allows the operations to be scheduled asynchronously, however, the question is now that most methods return Task<T>, would the context switching of all these asynchronous operations not have an adverse effect on the performance of the Web API? At the end of the day, async was added to improve the scalability but can adversely damage the performance? As we will see below, ASP.NET Web API runs actions asynchronously only if you tell it to - hence no context-switching happens within the framework for non-Task actions. And for Task actions, since we are dealing with long running processes, asynchronous processing provides scalability.

And here is the myth-busting:
TASK       ASYNC 
While Task<T> was designed and built to serve as an easy, approachable and consistent asynchronous programming model, it does not necessarily mean a Task<T> will run on a background thread or in the ThreadPool. In fact, this is very much the case for xxxAsync methods in the framework, as we will see shortly.

Have a look at the code below:

Thread.CurrentThread.Name = "Main Thread";
Func<string> f = () =>
 {
  Console.WriteLine(Thread.CurrentThread.Name);
  return "Ali";
 };
Task<string> t = new Task<string>(f);
t.RunSynchronously();
Console.WriteLine(t.Result);
// OUTPUT:
// Main Thread
// Ali


So as it can be seen above RunSynchronously will run the task in the current thread - hence the thread names are the same.

So what is Task then? I would like to describe Task as below:
Task is nothing but a wrapper class that encapsulates a delegate and its state (result, status, exception, etc)
In fact, it is the Scheduler (which can be passed as an argument to Start) which defines how the task should run. Default scheduler (when constructing the task without passing scheduler or using Task.Factory.StartNew()) runs the task in the ThreadPool. This is different from the original scheduler initially designed that used to have a dedicated scheduler with as many threads as CPUs on the box (see here for discussion on the subject).


Web API Pipeline

This subject deserves its own post which I will get to but in the meantime, let's look at the processing pipeline from the moment request is received by the server until action is called on the controller. 

This is an simplified view of the pipeline (which for now serves our purpose):


In terms of servers, currently there are two out-of-the box server scenarios in Web API:
  • ASP.NET Pipeline: this involves using IIS, IIS Express or Visual Studio Development Web Server (Cassini)
  • Self hosting
In terms of Self Hosting, HttpSelfHostServer receives the request and process it using 
ProcessRequestContext which passes a ChannelContext and RequestContext. This is reminiscent of good old ISAPI entry pointHttpSelfHostServer will call its base class's (HttpServer) SendAsync which is the first place we see the Task<T>:
protected override Task<HttpResponseMessage> 
    SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

This method is responsible for copying some context to the Thread Storage Area and HTTP request properties. But the returned task is not created in this method and is returned from its base class DelegatingHandler. This class does nothing but to call SendAsync on its inner handler (i.e. it delegates the call to another handler). This object is one of the classes inherited from HttpMessageHandler (in fact DelegatingHandler itself is such a derived class). In a typical Web API scenario, this class is HttpControllerDispatcher.

Dispatchers are responsible for finding the actual handler (in our case the controller) and preparing the state for its execution and final release of the handler. In this case, HttpControllerDispatcher does exactly that. But it is important that dispatcher here only returns the Task<HttpResponseMessage> returned to it by the controller, so again does not create the task.

Controllers are the ones doing the actual work hence the method name changes from SendAsync to ExecuteAsync. The bulk of the work is done in the ApiController. This class gathers controllerDescriptor, actionDescriptor and filters and in essence, returns HttpActionInvoker's InvokeActionAsync. Note that SendAsync changed to ExecuteAsync and now it is InvokeActionAsync.

We have not yet seen the creation of the task! But we are not too far off. Most of the heavy lifting is done in the private class ActionExecuter of ReflectedHttpActionDescriptor. This class compiles a lambda expression based on the return type of the action:
if (methodCall.Type == typeof(Task))
{
 // for: public Task Action()
 return ...
}
else if (typeof(Task).IsAssignableFrom(methodCall.Type))
{
 // for: public Task<T> Action()
 return ...
}
else
{
 // for: public T Action()
 return ...
}

If the return type is Task, or Task<T>, it will return the task. But what if it is a non-Task return type? Well, it executes the action to get the result and wraps it in a task:
var result = compiled(instance, methodParameters);
...
return TaskHelpers.FromResult(result);
TaskHelpers.FromResult simply creates a dummy task and sets the result.

How much of the Web API runs asynchronously?

Almost zero if you do not return Task or Task<T>! In order to investigate this, we will use a simple technique to trace the thread switching from the time request is picked up by the server (in this case Self-Host) all the way to the controller and then back again.

I use this simple code to name the current thread to the "class.method()" name if it already does not have a name - I also use a prefix for ability to filter these debug outputs from the rest. Remember that assigning a name to a thread already having a name throws exception. We also output the name using Trace.WriteLine():
using System.Diagnostics;

namespace System.Threading
{
 public static class ThreadNameTracingExtensions
 {
  /// <summary>
  /// if thread has a name, it leaves the name as it is. If it does not have a name,
  /// it sets the thread's name to the module.method
  /// It outputs as 
  /// </summary>
  /// <param name="thread"></param>
  public static void TraceName(this Thread thread)
  {
   var st = new StackTrace(new StackFrame(1));
   var methodBase = st.GetFrame(0).GetMethod();
   string name = string.Format("{0}.{1}()", methodBase.ReflectedType.Name, methodBase.Name);
   Trace.WriteLine(string.Format("__ThreadName__ => {0}: '{1}'", name, thread.Name));
   if (string.IsNullOrEmpty(thread.Name))
    thread.Name = name;
  }
 }
}

And now we just sprinkle this line of code in various points in the pipeline:
System.Threading.Thread.CurrentThread.TraceName();

Let's look at how this will behave for an action returning a string:
[HttpGet]
public string Test(int id)
{
 System.Threading.Thread.CurrentThread.TraceName();
 return "Test";
}

Here is the trace output (I have removed "__ThreadName__ => " prefix):


HttpServer.Initialize(): ''
HttpControllerDispatcher.SendAsync(): 'HttpServer.Initialize()'
ApiController.ExecuteAsync(): 'HttpServer.Initialize()'
<>c__DisplayClass3.<ExecuteAsync>b__0(): 'HttpServer.Initialize()'
ApiControllerActionInvoker.InvokeActionAsync(): 'HttpServer.Initialize()'
<>c__DisplayClass3.<InvokeActionAsync>b__0(): 'HttpServer.Initialize()'
ReflectedHttpActionDescriptor.ExecuteAsync(): 'HttpServer.Initialize()'
<>c__DisplayClass5.<ExecuteAsync>b__4(): 'HttpServer.Initialize()'
HelloWorldController.Test(): 'HttpServer.Initialize()'
So as you can see from above, the thread that initialised HttpServer, will call all the methods in the pipeline, including all those xxxAsync methods. Our action is also called synchronously by the same thread. Note anonymous methods created by lambda style delegate definitions all the way through the pipeline.

It seems to me that ASP.NET team have decided to add Async suffix to all methods that could be called asynchronously rather than would be called asynchronously. I would like to get a confirmation if it is the case or I am missing something since I am for now using Self-Hosting. In any case, I think this naming could be misleading and perhaps is a misnomer (although alternative ExecuteCanBeAsync is ugly!) but I trust the team had a good reason to use this name.


Now let's look at an action that returns a task: 

[HttpGet]
public Task<string> AsyncCall()
{
 System.Threading.Thread.CurrentThread.TraceName();
 var task =
  new Task<string>(
   () =>
   {
     
     System.Threading.Thread.CurrentThread.TraceName();
     Thread.Sleep(20 * 1000); // 20 seconds
     System.Threading.Thread.CurrentThread.TraceName();
     return "AsyncCall";
   }
  );
 task.Start();
 return task;
}

And here is the output:

ApiController.ExecuteAsync(): 'HttpServer.Initialize()'
<>c__DisplayClass3.<ExecuteAsync>b__0(): 'HttpServer.Initialize()'
ApiControllerActionInvoker.InvokeActionAsync(): 'HttpServer.Initialize()'
<>c__DisplayClass3.<InvokeActionAsync>b__0(): 'HttpServer.Initialize()'
ReflectedHttpActionDescriptor.ExecuteAsync(): 'HttpServer.Initialize()'
<>c__DisplayClass5.<ExecuteAsync>b__4(): 'HttpServer.Initialize()'
HelloWorldController.AsyncCall(): 'HttpServer.Initialize()'
HelloWorldController.<AsyncCall>b__0(): ''
HelloWorldController.<AsyncCall>b__0(): 'HelloWorldController.<AsyncCall>b__0()'
So as we can see, the initial thread runs the code including the action. However since we are doing the actual work in an action, action is called in a background (ThreadPool) thread - note the last two lines. 


So as we have seen, unless you return a Task or Task<T>, all the pipeline runs synchronously.

Synchronisation

OK, with task-based operations all through the pipeline, one would expect to see some synchronisation code. But where are they? I had to look for a while to see them.

ASP.NET Web API - from what I have learnt from the source code - uses two modern synchronisation mechanisms (rather than classic WaitOne, WaitAll):

  • Task.ContinueWith<T>: this will ensure that the continuation will run in case of successful running of the task. So basically the thread that created the task does not have to wait instead it can define a piece of continuation code to run at the end of the task -  so the synchronisation in fact happens on the background thread. There are numerous places where this technique is used.
  • SynchronizationContext.Post: This is a low level synchronisation technique that is useful only if SynchronizationContext.Current is set.
SynchronizationContext.Current is very important and it synchronises tasks (when they are asynchronous) with the ASP.NET Thread.


Task continuation is a clever synchronisation. Surely the continuation has to wait for the task to finish but the creator of the task has to wait for neither the task nor its continuation. And analogy is the car in the repair garage. If I leave the car in the garage for repair, they will call me to pick up the car - which can be anytime and perhaps I might be too busy to pick it up. But if I ask them to call my wife to pick up the car, my work will not be interrupted - not that my wife will accept to do this favour! It is just an example.

Conclusion

ASP.NET Web API actions (and all the pipeline methods) will be called asynchronously only if you return a Task or Task<T> . This might sound obvious but none of the pipeline methods with Async suffix will run in their own threads. Using blanket Async could be a misnomer. [UPDATE: ASP.NET team indeed have confirmed that the Async is used to denote methods that return Task and can run asynchronously but do not have to]

ASP.NET Web API uses Task continuation for synchronisation. In essence this synchronises the continuation with the background thread in another background thread.

Disclaimer

This article is the result of exploratory debugging of the Web API source code. Some of the information provided might not be accurate but I will make sure the post is updated and maintained if corrections are fed back to me.


Saturday, 7 April 2012

ASP.NET Web API beta Source code: Survival Guide

[Level T2]
NOTE on 01/06/2012: ASP.NET Web API RC was released last night (31/05/2012). This means for a while at least, you do not have to build the nightly releases. You can download it from here.

Just a quick note that as you probably know, ASP.NET Web API beta (along with ASP.NET MVC 4 beta) is out. Scott Guthrie announced the release in his blog on 27th of March and it has been released under Apache 2.0 license.

You may download the source code from here via git or web . This is a really good news for all who wanted to have a deep dive into the implementation and extensibility points of the framework - including me. The media was also surprised on the release as it shows perhaps another shift in Microsoft towards community-oriented software development - but I will leave this subject for another occasion.

It is interesting that the source code comes with full unit testing coverage, yet it does not use MS Test framework available in Visual Studio instead it uses xUnit, a framework among whose contributors is Brad Wilson. This gives us a bit more insight into the way ASP.NET team work who are arguably among the most popular teams in Microsoft.

Downloading the source is all fine. Yet I had a few teething issues with getting it working which I share so that others having similar problems could find their way out.

Building the framework source code

OK, as soon as you have downloaded and unzipped the source, just open the solution. Since this source relies heavily on NuGet packages yet it does not contain binaries, it needs to re-download the packages. There are instructions on the page but I personally could not get it working. 

So first thing to do is to right-click on the solution and click on "Enable NuGet Package Restore" as below [UPDATE: You actually can ignore this step, and do not have to set this value. I managed to build without this step]:


Now, if you attempt to build, you will get the error below:

error : NuGet package restore is not currently enabled. For more information, please see: http://aspnetwebstack.codeplex.com/wikipage?title=NuGet+Packages

Solution is to go to Tools -> Options -> Package Manager -> Package source and add the address below:

http://www.myget.org/F/f05dce941ae4485090b04586209c8b08/
Now you need to rebuild the packages as advised in the ASP.NET web stack page:

build RestorePackages

And now finally rebuild the solution and this time it will work. As the link above describes, this NuGet feed is not quite official and is used for out of band releases - which this source code certainly is.

Now you might get this error again if you try rebuilding having added the new NuGet feed. Not to worry, delete the source code, unzip again, Enable NuGet Package Restore and then build. This time should work.

Using Web API Source code

One of the best ways to understand a source code is to see it running and debugging it. And that is what I tried to do. 

I had already installed ASP.NET Web API/MVC beta from the installer. So here is what I did: created an ASP.NET Web API project (see Part 1 for more details), added the project to the Web API source code, removed references to the ASP.NET Web API/MVC beta DLLs and added project reference to those DLLs I needed from its source. Easy! Well, not so fast...

The problem is if you have installed the ASP.NET Web API, all binaries are already GACed and they take precedence over the project references. You can verify this by looking at the list of DLLs loaded in the output window while debugging. Now this by itself is not a problem, but considering the source to be newer with breaking changes, it becomes a different matteeeerrr...

Now courtesy of Christoph De Baene, this also has a solution. I was lucky to find about his post just from yesterday as he was quicker to see the problem and find a solution. He explains about using Environment variable so CLR looks the development path first:

To resolve this problem we can use DEVPATH. It’s an environment variable that you can set to a folder (typically you’re output folder). The runtime will use the DEVPATH folder for probing before looking into the GAC!

Setting DEVPATH environment variable


You also need to add the entry below to your config file (app.config or web.config depending on your project):
 

 <configuration>
   <runtime>
      <developmentMode developerInstallation="true"/>
   </runtime>
 <configuration>
 
OK, now it is time to run the code. Well, I ended up using Christoph's code but still having issues this time "Method not found":

Method not found: 'Boolean System.Net.Http.Headers.HttpHeaders.TryAddWithoutValidation(System.String, System.String)'.

Well, it turns out this time that the version of the System.Net.Http DLL has also moved on and I used the one coming with the installer. However, while Microsoft has decided not to include this assembly's source code along with the rest, source has indeed moved on and you need to use the one in the packages folder underneath the solution.

Now I did that and still not working! I was pulling my hair out and went through a few things and realised references were not set to "Copy Local". Once I set that to true, it started working.

Conclusion

The process of building and running the ASP.NET Web API (and MVC) is a bumpy ride. There are quite a few additional things you have got to do to get it working.

In brief, here are the steps you need to do to be able to debug the source code if you have installed ASP.NET Web API beta installer (see above for details):
  1. Create a DEVPATH environment variable and set to your debug output folder
  2. Add an entry to your config to flag VS to use DEVPATH
  3. Make sure all your references are "copy local" set to true
  4. Make sure you add reference System.Net.Http.dll using "Manage NuGet packages" and not from the GAC