共用方式為


Introducing ASP.NET MVC 4 Beta with Web APIs

There has historically been in Microsoft many ways of doing the same thing. That’s one of the original goals of WCF when it was created: unify the 5 or so different ways of creating distributed applications using the Microsoft stack (ASMX services, COM+, .NET Remoting, MSMQ and one more which I don’t remember). Whether it succeeded in making this unification is another story, but for a while the “official answer” for building distributed applications was WCF. XML was supposed to solve all the problems in the world, and WCF was a decent framework built on top of XML to build service-oriented solutions (i.e., SOAP) in a very pluggable way.

Fast forward a few years, XML didn’t bring world peace as it promised, and non-SOAP architectures started having a higher and higher predominance in the world, especially those revolving around HTTP and REST. Starting on the .NET Framework version 3.5, WCF started paying some attention to the HTTP/REST space with the introduction of the WebHttpBinding and WebHttpBehavior classes, the System.ServiceModel.Web namespace and the whole Web programming model. On the version 4.0, a lot more features were added to the framework, which collectively were called WCF Web HTTP Services. Starting at the end of 2010, the WCF Codeplex project started previewing new features which would eventually be made into the framework, which evolved into the WCF Web API project and the new HTTP programming model.

Backtracking a little, Microsoft also had another way of building “services” for web clients, namely services which accepted a variety of parameters and returned JSON (natively consumed by JavaScript apps), which was the JsonResult class in the ASP.NET MVC framework. In fact, quite a few people have approached me and other people in Microsoft with a variant of the same question: if I’m building web services to be consumed by JavaScript clients, which one should I use, MVC controllers, WCF Web APIs or “plain old WCF”? That was a valid question, and internally we decided to merge the technologies so that we could get the best of both worlds. As was announced today, the ASP.NET Web APIs are available for download along with the ASP.NET MVC 4 Beta release.

What exactly does it mean? First, notice that there’s no WCF in the “official” name – if you’re building Web APIs hosted on IIS, WCF isn’t used at all. But, unlike “classic” ASP.NET MVC applications, Web APIs can also be hosted outside of IIS (or self-hosted), in which case WCF is used as the underlying transport channel. So if you’re used to WCF (or the “old” WCF Web APIs), you may need to learn some new terminology. Some changes are simple, some are a little deeper.

Goodbye Services and Operations, Hello Controllers and Actions

A WCF is built based on a service – which is the root of everything. A host knows about a service, which can have endpoints. A service is some class which implements some interface (decorated with the ServiceContractAttribute), and whose operations are also decorated in an “opt-in” model (you can create “POCO” services, but it requires a lot of work to set up). ASP.NET Web APIs are based on controllers, classes which derive from a new ApiController class. The operations in the class don’t need to be annotated with any attributes, and they’re exposed as actions (actions and operations refer to pretty much the same thing).

There’s also no “service host” to serve as the entry point for requests. In a concept familiar for those used to ASP.NET MVC, the new system is completely based on routing – before a request can make its way to an action (a.k.a. a method in the controller class), the request URI must match some routing in the route table which will lead it to the appropriate controller and action. Notice that there’s no centralized service host – any controller type which happens to be loaded in memory can be routed to. Also, the routing is in many cases based on conventions. If a method in the controller class is called “Get”, then HTTP GET requests which get to that controller are routed to that method. Likewise, a method called “Post” (or “Delete”, “Put”) will have requests with the corresponding HTTP method routed to it by default.

Model binding

Another major difference between “classic” WCF and the ASP.NET Web APIs is how the parameters to the operations (I mean, actions) are populated. Previously, parameters in WebGetAttribute-decorated operations would have their values coming from the query string, and for operations decorated with WebInvokeAttribute, they’d come from the request body (unless the UriTemplate of the attribute had bound the parameters from some part in the URI). ASP.NET Web APIs follows, by default, the way that ASP.NET MVC populates the parameters, which is using model binding.

Models, in the context of Web APIs, are nothing more than a fancy name to describe the parameters of the operations in the controller class. Model binding is the process by which the framework takes parameters from different places in the request and binds them to the action parameters. This seemingly small change can be quite surprising for people used to the “WCF way”. Notice that the actions don’t need to determine where their parameters are coming from – they can come from the URI, from the body, or from any place where the value providers registered in the system can get them from. This is quite handy for accepting things such as HTML forms (which is – finally! – supported out-of-the-box) and parameters which can come from places even as HTTP headers.

I won’t spend too much time on model binding in this post, but this article has a good introduction to the subject. One thing which is good to note is that model binding can be “turned off” (which would revert to the basic deserialization rules), but that’s a topic for another post.

More features

There are a lot of new features in the new APIs, some of them I’ll briefly mention here (and will possibly cover them in future posts)

  • First-class HTTP support: don’t want to use CLR types? No problem. Your actions can work directly on HttpRequestMessage and HttpResponseMessage objects.
  • Content-negotiation: out-of-the-box support for negotiation of response content, using formatters (similar to the last preview bits of the WCF Web API)
  • HttpClient: a modern HTTP client for .NET. Henrik Nielsen (an architect in our team) has posted some examples of this library
  • Service resolver: a centralized place to do things such as dependency injection
  • System.Json: first-class support for treating JSON in an untyped way, without needing to serialize / deserialize between that format and CLR types
  • Improved testability: as a side-effect of the HttpClient library and the service resolver; it’s possible to “host” a controller and send requests to it directly, without going through the network at all
  • Query composition: support for actions returning IQueryable<T> and sending filter / take / skip / order parameters in the query string which affect how the response is returned
  • Filters: something similar to inspectors in WCF, where you can hook up user code in various parts of a request dispatching
  • Message handlers: I’d say that they’re similar to channels in WCF where you can get messages passing through the system, but that’s a disservice to the handlers. Channels in WCF are almost impossible to write, while message handlers are actually quite easy (once you get acquainted to the new Task asynchronous programming model)

There are probably some other features which I forgot, and remember that this is a Beta release, so it’s possible that we’ll change some of the implementation before we ship the “final” version

Coming up

This is a lot of information for a single post. I’ll post a few examples in the next few days / weeks to show up how this can be used. I won’t call it a “series” as I’m done with that (for the time being), though.

Your turn now. Try it out and let us know what you think!

Comments

  • Anonymous
    February 16, 2012
    Ow! Very, very good news.
  • Anonymous
    February 16, 2012
    I know some things have been removed from the framework e.g. the test client for one. What other "breaking" changes are there moving from WCF WebAPI to ASP.NET WebAPI. Are operation handlers still there?
  • Anonymous
    February 16, 2012
    Operation handlers don't exist anymore. Their functionality can be implemented mostly with filters (especially action filters). Other features which aren't in the Beta include support for WebGet/WebInvoke attributes and UriTemplates (the scenario can be implemented with routes), support for the help page (which existed even in WCF WebHTTP from .NET 4.0), and any support to the WebOperationContext (this is gone; in general there are very little static / global variables in the new product).Notice that some of those features will likely be implemented before the final release of the product (for resourcing constraints some of them had to be left off the Beta release).