I’ve been receiving lots of emails asking my opinion about ASP.NET Web API lately. One of the most recent messages boiled them all down pretty well in its subject line:

ASP.NET Web API – Why is it so cool?

That’s a great question.

Too many of the answers to that question come down to subjective, personal preference. Worse, you’ll often hear that it’s what you should use simply because it’s the new thing Microsoft is pushing (you know, like WCF once was). If you’re already making good use of ASP.NET MVC’s controller actions as a makeshift API, just hearing that Web API is “better” might not be all that compelling.

However, I think Web API objectively wins out over MVC controller APIs in a few key areas. In this post, I’ll cover why these three aspects of ASP.NET Web API make it a clear choice for my ASP.NET-based APIs going forward:

  • Content negotiation
  • Flexibility
  • Separation of concerns


Content negotiation

Content negotiation is one of those features that can seem overwrought at first glance. The technical demos we’ve seen most often, returning content like images and vcards based on the Accept header, are neat, but not something you’re likely to need on a daily basis.

However, content negotiation is still a nice feature even if you only expect to return a single type of serialization. Why? Because it decouples your API code’s intent from the mechanics of serialization.

For example, which would you rather write and maintain?

ASP.NET MVC

public class TweetsController : Controller {
  // GET: /Tweets/
  [HttpGet]
  public ActionResult Index() {
    return Json(Twitter.GetTweets(), JsonRequestBehavior.AllowGet);
  }
}

ASP.NET Web API

public class TweetsController : ApiController {
  // GET: /Api/Tweets/
  public List<Tweet> Get() {
    return Twitter.GetTweets();
  }
}

The choice between those two options is an easy one for me. Not only is the return value of List<Tweet> more expressive (especially when you revisit this code in a year or two), but letting Web API handle the serialization means you don’t need to clutter the action up with the Json() code.

Of course, you never know when it might be helpful someday for that same endpoint to support returning its data as XML, CSV, MessagePack, or some future serialization format. Content negotiation makes adding that across an entire API relatively simple with Web API, but it would be cumbersome to update a plethora of MVC controller actions.

Flexibility

It’s clear that flexibility was a central goal in Web API (without resorting to the configuration tedium that burdened WCF). Content negotiation is a great example of that, but that’s only the beginning. Web API starts with sensible defaults, but then provides a GlobalConfiguration object that you can use to tweak a wide range of options.

A couple more concrete examples:

Down with XML!

One initially disconcerting thing about Web API is that hitting an endpoint in your browser will result in an XML response. That’s correct behavior because regular requests in browsers usually send an Accept header preferring text/html and application/xml, but not JSON.

If you want to bring Web API’s behavior more in line with the output of MVC’s Json() helper, you can remove XML support from your API entirely. Just add this to the Application_Start event and you’ll never see XML again:

// Normally, you'd probably be doing this in a setup method that
// accepts the configuration as a parameter and this line wouldn't
// be necessary, but you can do it right in Application_Start too.
var config = GlobalConfiguration.Configuration;
 
config.Formatters.Remove(config.Formatters.XmlFormatter);

Now, even if a client’s Accept header prefers XML over JSON, Web API won’t respond with XML. Personally, I’d prefer to see Web API prefer JSON over XML by default, but it’s great that Web API is flexible enough to allow these global changes with a minimum of configuration ceremony.

Tweaking your API’s JSON format

You’re generally stuck with the JSON that JavaScriptSerializer wants to generate when you use MVC’s Json() helper. Luckily, JSS does a pretty good job of creating sane JSON, but it also opts you into some unusual conventions like “MSAjax” date encoding instead of the more common ISO format.

Web API and Json.NET allow you to tweak the JSON that your API produces very easily. For example, Json.NET defaults to using ISO dates, but you can switch that to the Microsoft format for backwards compatibility across your entire API with a simple configuration setting:

// Separate statements for purposes of fitting within my tiny
// 492px code blocks. You could do this on one line if you wanted.
var js = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
 
var dfh = js.SerializerSettings.DateFormatHandling;
 
dfh = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;

There’s a wide range of options you can set this way, from “pretty printing” the JSON to support for automatic translation between camelCase and PascalCase. For more examples, see this article on the ASP.NET site.

Separation of concerns

All of the preceding examples highlight one of my favorite overall advantages of using Web API. It’s possible to quickly drop these high-impact changes in across an entire API largely because Web API helps separate your API from the part of your project that returns HTML.

MVC controller actions are optimized for building up an HTML document through the use of things like views, partial views, and HTML helpers. That whole pipeline doesn’t really make sense in the context of an API that returns entities, DTOs, or ViewModels, and I think it’s valuable to keep them separate.

So separate, it’s not tied to a website at all

In fact, you may eventually want to isolate API from your website to the point that it doesn’t even make sense to host the API within the same project. With Web API, you can self-host the same API code in a Windows Service or even a console app.

You could do that with an ASP.NET MVC “API” by creating a separate project for the API, but then you’re still paying the performance penalty for your API requests to filter through MVC’s rendering pipeline. In simple load testing on my local machine, I’ve found that Web API endpoints hosted in console apps are nearly 50% faster than both ASP.NET controller actions and Web API endpoints hosted within MVC projects.

It’s great to have that low-cost, high-performance option as usage of your API grows. Starting with Web API means you’re not tied to ASP.NET MVC (or any web framework) in the future. It’s quick and easy to migrate an MVC-hosted Web API to a centralized project of its own as your needs organically grow.

Conclusion

These are the three main reasons why I’m using Web API controllers for client-side callbacks in my ASP.NET MVC projects going forward. Even though many of those “APIs” will never grow into more than endpoints for AJAX callbacks, using Web API for those endpoints is still easier and more flexible than other built-in alternatives.

What do you think? Are you using Web API yet? Do you plan to migrate from MVC controller actions to Web API in the future? Did I miss an aspect of the MVC-centric approach that makes it work better than Web API for you (I can think of one, but I haven’t seen many projects actually doing this in the real-world anymore)?