IHttpActionResult - new way of creating responses in ASP.NET Web API 2

Strath

June 30th, 2013

IHttpActionResult – new way of creating responses in ASP.NET Web API 2

Building rich applications and returning HTML is now easier than ever!

In the first version of Web API, you had two ways of creating response from an API action. Either return a specific object instance (or void) and let the Web API pipeline convert that to an HttpResponseMessage for you, or return a raw HttpResponseMessage. In that case, you had to construct it manually, and you bypassed all of the internal Web API mechanisms (formatters, content negotiation).

Now in Web API 2 (which was just released in beta) we get a third option, which is IHttpActionResult. It’s very simple, yet extremely powerful – so let’s explore it in this blog post.

Adding ASP.NET Web API 2 beta

To be able to follow this blog post you’d need a new project with Web API 2 installed. This can be done very easily as the packages are now on Nuget.

I use a console app and a self host, so we’ll install a self host package.

This should pull v5.0.0-beta2 of ASP.NET Web API, otherwise known as Web API 2.

We’ll use a standard self host to play around:

Introducing IHttpActionResult

IHttpActionResult is not revolutionary in any way, as it simply builds around the familiar HttpResponseMessage, but it is tremendously useful. It is effectively a factory for HttpResponseMessage, and by implementing the interface you provide instructions on how a new response should be constructed.

The interface has just one method:

Then, instead of returning an instance of an object or a raw HttpResponseMessage, you can return IHttpActionResult and Web API will follow your instructions coded in there.

With this in place, you get a hold of a powerful mechanism allowing you to re-use sets of instructions, to compose a specific type of response, between different actions – which in many ways is similar to what ASP.NET MVC does with its ActionResult.

Implementing a sample IHttpActionResult

One situation of where IHttpActionResult will come in handy is when you’d like to preset specific headers/properties of HTTP response. For example, when responding to a POST request, you’d like to automatically set the status code to 201 (created) and set the location header.

It’s very easy now:

And you can use it in your controller just like that:

This will produce the desired output.

This way, instead of duplicating the code constructing such HttpResponseMessage across different controllers, or hiding it in some helper classes or a base class, we have a very verbose code base where we immediately know what’s being returned and under which circumstances.

Serving HTML with IHttpActionResult

Another great possible use case for IHttpActionResult is supporting HTML with Razor. You can now very easily define an HTML action result which would parse the Razor views.

This way you can build fully fledged web applications, with proper HTML templating support, and forget about MVC altogether.

Of course this is nothing new, because it was possible before with Web API too, using dedicated RazorMediaTypeFormatters (for example WebAPIContrib has a great one) – but it felt very hacky, as Web API didn’t lend itself to such uses cases well, especially if you wanted dedicated HTML pages (= not served via other media types).

With IHttpActionResult we can simply do something like this (mind you, this uses RazorEngine package from Nuget):

So we take in a view name and a model, and then read the view from the disk and parse it. Then we return an HttpResponseMessage with content type text/html based on that. By the way – because I’m demoing this against a self hosted console application I hardcoded the view folder in there too.

Now all we need is just a view:

And a controller:

Here I simply use the page variable from the route data to identify the view. We probably also want a separate route for the “html” side of our Web API application so I’ll throw it in too (after our default API route, since it’s very greedy):

And now if we navigate to that controller in the browser, we get the HTML page served:

Summary

Overall, IHttpActionResult is extremely useful interface for Web API developers. It is something that was very needed – as an alternative to forcing developers to deal with formatters.

By declaring your own custom results, you can streamline lots of processes and easily achieve the desired output of your actions. And, as shown in the examples, you can even go beyond the pure API, and use Web API as an end-to-end robust web application platform with HTML serving.

Be Sociable, Share!

  • http://superlogical.io/ Jake Scott

    It would be pretty easy to add Nustache view engine too… that way you don’t reply on anything from razor (which has too many dependencies on asp.net mvc to be useful)

    There is an example of how to set it up with a master layout here: https://github.com/jdiamond/Nustache/blob/master/Nustache.Mvc3/NustacheView.cs

    Obviously you would need to tweak it to get it to work with IHttpActionResult..

    With Mustache it would be possible to share client and server side templates… so render on server or client!

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1388

  • Pingback: Dew Drop – July 1, 2013 (#1,576) | Alvin Ashcraft's Morning Dew

  • Bruce Chen

    Hi,
    I follow your post to try IHttpActionResult, but always response 404

    {
    “Message”: “No HTTP resource was found that matches the request URI ‘http://localhost:999/api/Test’.”,
    “MessageDetail”: “No type was found that matches the controller named ‘Test’.”
    }

    I try in VS2013 Preview and VS2012 same message.

    Can you help me?

    • Enteri

      I am getting a similiar result
      http://localhost:49460/api/v1/WallFeed/WallPosts
      {“Message”:”No HTTP resource was found that matches the request URI ‘http://localhost:49460/api/v1/WallFeed/WallPosts’.”,”MessageDetail”:”No action was found on the controller ‘WallFeed’ that matches the request.”}

      • http://www.strathweb.com/ Filip W

        can you post the controller and route config?

  • Priya

    Seems a little similar to using a delegating handler to control the output, but certainly cleaner

  • Pingback: ASP.Net Web API 2 – O que há de novo? - TI Especialistas

  • Martin Fabik

    why would you want to return HTML ?? Web API should be all about returning pure data. If want do HTML on the server side use ASP.NET MVC.

    • http://www.strathweb.com/ Filip W

      you can only use MVC on IIS. There are many scenarios where you’d host Web API outside of IIS.

      • Martin Fabik

        Yeah I guess thats the only exception.

        • http://www.strathweb.com/ Filip W

          I wouldn’t say it’s exception, another example is if you host with OWIN on top of Katana.

          Also, even if you host on IIS you may want to choose Web API for HTML and not use MVC at all because you don’t want to couple yourself to System.Web.

    • GroovBird

      I disagree. HTML is just a different representation of the same resource. You’d want that resource to be represented as JSON when requested from an AJAX call and return HTML when requested from the address bar.

  • Whoever

    Shouldn’t HTML be part of the WebApi content negotiation? It seems all other framework has it built in except Microsoft.

    • GroovBird

      Yes, but it is. There’s multiple ways to do it. Content negotiation is my preferred method too.

  • Pingback: New Features in ASP.NET Web API 2 – Part I

  • Pingback: What is New in ASP.Net Web API 2 IHttpActionResult and CORS - Part 2

  • GroovBird

    I’m only starting to grasp this now, and I may be completely delirious here, but what a missed opportunity this was! The ExecuteAsync method does not get the HttpRequestMessage passed, which means it has to be passed by the action method, at which point I’m trying to completely remove the dependency on the Request property of the controller so I can 1) test that action method to see that it returned the correct kind of IHttpActionResult instance with the right properties set and 2) call my controller from other controllers, both without worrying about faking a Request.

    Tell me I’m wrong, please.

    • http://www.strathweb.com/ Filip W

      I am not sure I follow what you are trying to do.
      If you have a need for HttpRequestMessage in IHttpActionResult, just pass it from the action in the constructor. Then in the test you’d test IHttpActionResult separately anyway, so there is no need to fake anything.

      • Dave Van den Eynde

        What I want to do is simple: I want to write action methods that have no need for the Request property assigned to the controller by the stack. I want my everything bound to parameters and everything that has to go out via the result, without ever needing an HttpRequestMessage. Not just for testing, but also to be able to call another action method in another controller from the method that was invoked.

        I can do this now, for 90% of the requests, by having parameter bindings for certain headers like If-Modified-Since and ETag, and by having properties like LastModified on my model (bearing a [JsonIgnore] attribute as not to include it in the payload) but what I can’t do is set the Location header for a POST when I really don’t want to send back any model so that it renders into a 204 No Content.

        Enter the IHttpActionResult. If I could construct an IHttpActionResult from the action method that did not need a Request, I would be all set, but because Microsoft chose not to include the request in the ExecuteAsync signature, I’m forced to pass it to the constructor from the action method, where I want to avoid touching the Request.

        I don’t want to touch the request, because then I would have to fake it. Try calling a Web API controller from an MVC controller because you want to embed some information and avoid an unnecessary request from the client.

  • Pingback: Top 5 New Features in ASP.NET Web API 2 | Web Development Tutorial

  • Pingback: Top 5 New Features in ASP.NET Web API 2 | Web Development Tutorial

  • Bradley Eastes

    Hi There, This is awesome and I enjoyed implementing it! However, I have an issue, I want to use the @Html helper tag (E.g. @Html.DisplayNameFor(Model => Model.Title)) in my .cshtml files but I get the following error:

    {“Unable to compile template. The name ‘Html’ does not exist in the current contextnnOther compilation errors may have occurred. Check the Errors property for more information.”}

    Any idea’s?