web-api

Extending RestSharp to Handle Timeouts in ASP.NET MVC

We're working on a large project which consumes a custom-build API, and one of the requirements of this project is that if the API goes down, certain sections of the website still need to be able to function. The reason for this is that our app consumes a lot of APIs and services, and occasionally a non-critical one will go down (for maintenance, bugs, whatever) and we don't want our site to crash as well, since this was a problem that plagued the previous version of this app.

To do this, we needed a way to ensure that if a non-critical service or API went down, we could record the fact that a request to said service timed out and NOT throw up a scary-looking error page to our users. We're using the incredible RestSharp library to consume our API, so it occurred to me that the best place for this timeout-handler to exist was in some kind of common class that extended RestSharp's basic functionality. This post lays out what we built in order to record timeouts from our APIs and services (and, as always, a demo application can be found over on GitHub).

API Setup

I've set up the sample project in much the same way that our real project is set up. Closest to the data store (e.g. the "bottom" layer of the stack) is the API, which will create data for our ASP.NET MVC application to consume.

For this demo, let's create a simple API which returns the current date and time.

[RoutePrefix("home")]
public class HomeController : ApiController  
{
    [HttpGet]
    [Route("date")]
    public IHttpActionResult GetDate()
    {
        var rand = new Random();
        Thread.Sleep(rand.Next(1, 100));
        return Ok(DateTime.Now);
    }
}

The call to Thread.Sleep() exists to show that we can handle situations where the API doesn't respond. Any call to this API method will be delayed between 1 and 100 milliseconds before responding. (Just to be clear, don't use that call in production applications.)

Building the Base Client

In order for our ASP.NET MVC app to consume our API, we build classes known as clients, which implement an interface from RestSharp called IRestClient. Normal usage of RestSharp dictates that we create a class which implements that IRestClient interface.

But we have a different scenario than is covered by the normal usage. We need to determine a way to ensure that our clients can handle timeouts, and in a uniform manner. To accomplish this, let's implement a base client class from which all our other clients will derive.

public class ClientBase : RestSharp.RestClient  
{
    public ClientBase(string baseUrl)
    {
        BaseUrl = new Uri(baseUrl);
    }
}

Notice that the base class inherits from RestClient rather than implementing IRestClient.

This base client will need to override the existing Execute() methods in RestClient to have them call our Timeout checking method. Here's the four methods we want to implement (as well as the implementation of the Timeout check):

public class ClientBase : RestSharp.RestClient  
{
    public ClientBase(string baseUrl)
    {
        BaseUrl = new Uri(baseUrl);
    }

    public override IRestResponse<T> Execute<T>(IRestRequest request)
    {
        var response = base.Execute<T>(request);
        TimeoutCheck(request, response);
        return response;
    }

    public override async Task<IRestResponse> ExecuteTaskAsync(IRestRequest request)
    {
        var response = await base.ExecuteTaskAsync(request);
        TimeoutCheck(request, response);
        return response;
    }

    public override async Task<IRestResponse<T>> ExecuteTaskAsync<T>(IRestRequest request)
    {
        var response = await base.ExecuteTaskAsync<T>(request);
        TimeoutCheck(request, response);
        return response;
    }

    private void TimeoutCheck(IRestRequest request, IRestResponse response)
    {
        if (response.StatusCode == 0)
        {
            //Uncomment the line below to throw a real exception.
            //throw new TimeoutException("The request timed out!");
        }
    }
}

We overrode these particular methods to handle four scenarios:

  1. Execute() handles situations in which we don't expect response data (meaning we will get a IRestResponse object with things like the HTTP status code, but we won't get any further data out of it).
  2. Execute<T>() handles situations in which we DO expect response data from the API.
  3. ExecuteTaskAsync() handles scenarios in which we want to asynchronously call the API and don't expect any response data.
  4. ExecuteTaskAsync<T>() handles the final scenario, in which we want to asynchronously call the API and expect to get response data back.

I want to draw particular attention to the TimeoutCheck() method. As far as I can tell, the way RestSharp denotes a timeout is to give the generated Response object a StatusCode of 0. This seems like it could also represent other scenarios, and so if anyone out there has a better way for me to specifically identify timeouts, I'd love to hear it.

Anyway, with the base class now implemented, we can build out client.

Building the Clients

We need to build a specific Client which will consume the API method (GetDate()) that we defined earlier. This class will need to both inherit from ClientBase (to get the custom method we wrote in the previous sections) and implement IRestClient (to get the additional functionality provided by RestSharp). For completeness's sake, we will also implement asynchronous and synchronous versions of the same call.

Here's the complete DateClient class:

public class DateClient : ClientBase, IRestClient  
{
    public DateClient() : base(Constants.BaseApiUrl) { }

    public DateTime? GetDate()
    {
        var request = new RestRequest("/home/date");
        request.Timeout = 50;
        return Execute<DateTime?>(request).Data;
    }

    public async Task<DateTime?> GetDateAsync()
    {
        var request = new RestRequest("/home/date");
        request.Timeout = 50;
        var result = await ExecuteTaskAsync<DateTime?>(request);
        return result.Data;
    }
}

Notice that the request.Timeout property is set to 50 milliseconds. Remember that our API will delay for a random amount of milliseconds between 1 and 100. This setup ensures that we can test our ability to handle timeouts. In the real world, you would set the Timeout property to something considerably more sane than 0.05 seconds.

More importantly, note that these methods return a nullable DateTime?, whereas the API method returns the non-nullable DateTime. This is because if RestSharp does not get a response, the IRestResponse.Data property will be set to the default value of the object it is trying to deserialize (e.g. the T in Execute<T>()). Because we set it to nullable, we automatically know that a null value is the error case, and can handle it accordingly.

Completing the Demo

We only need a couple more pieces to complete the demo. First, let's build an MVC controller which implements both the synchronous and asynchronous versions of our Client methods:

[RoutePrefix("home")]
public class HomeController : Controller  
{
    [HttpGet]
    [Route("index")]
    public ActionResult Index()
    {
        var client = new DateClient();
        var model = new HomeIndexVM();
        model.CurrentDate = client.GetDate();
        return View(model);
    }

    [HttpGet]
    [Route("async")]
    public async Task<ActionResult> Async()
    {
        var client = new DateClient();
        var model = new HomeIndexVM();
        model.CurrentDate = await client.GetDateAsync();
        return View("Index", model);
    }
}

We also need to build a simple Index.cshtml view to display the current date and time:

@model RestSharpTimeoutDemo.MVC.ViewModels.Home.HomeIndexVM

@{
    ViewBag.Title = "Home Page";
}

@if (Model.CurrentDate.HasValue)
{
    <h1>The current date/time is @Model.CurrentDate</h1>
}
else  
{
    <h1>The request timed out!</h1>
}

Finally, we can run the app. Sometimes we will get the error version of this page:

But, when the call doesn't timeout, we will correctly display the date and time.

The important thing is that either way, the user is not taken to some unhelpful error page (or, God forbid, the Yellow Screen of Death), and instead remains in the app where s/he can actually get some work done and not be blocked because we couldn't display the current date and time. If our goal was to get out of the user's way, I daresay this achieves that feat.

Summary

RestSharp is wonderfully extensible, and we took advantage of that to create a common client that handles timeouts. This client allows us to step out of our user's way to provide a more seamless user experience by, essentially, not throwing up a big yellow flag which screams SOMETHING WENT WRONG. And that, I feel, is a win.

If you want to dive deeper into this problem (or see something you could improve), check out the sample project on GitHub!

Happy Coding!

Post image originally by @raysato and modified by me.

A Simple Caching Scheme for Web API using Dependency Injection

I use Dependency Injection (DI) quite a bit in my ASP.NET projects, particularly in Web API and MVC web applications. Recently, I had a need to implement a caching layer in one of my MVC apps, and such a layer would be best used if it could be injected into my clients layer (e.g. the layer that called an API and handled responses from the same). The solution I came up with seemed to be pretty simple, so I wanted to share it here.

In this post, we're going to set up a simple MVC project that consumes a Web API and implements a caching layer.

Requirements

For this project, I'm using two of my favorite NuGet packages:

The sample project, which is over on GitHub, is a fully-functional implementation of the strategy described in this post. Feel free to check it out, branch it, download it, whatever!

Setting Up the API

First, let's take a look at our sample API. Here's the class DateNumberObject, which represents a response returned from the API to the web project:

public class DateNumberObject  
{
    public DateTime CurrentDate { get; set; }
    public int RandomNumber { get; set; }

    public DateNumberObject()
    {
        CurrentDate = DateTime.Now;
        Random rand = new Random();
        RandomNumber = rand.Next(1, 200);
    }
}

As you can see, all this class does is return the current date and time and a random number.

We can now build our API, which is also rather simple. Here's a snippet from the API's controller:

[RoutePrefix("samples")]
public class SampleController : ApiController  
{

    [HttpGet]
    [Route("date")]
    public IHttpActionResult GetDateAndNumber()
    {
        return Ok(new DateNumberObject());
    }
}

That's all our API will do: return the current date and a random number. Since there's no caching taking place at the service layer, we will need to implement caching at the web layer.

Speaking of the web layer, in our sample solution it is an MVC5 project, and we will be using my favorite Dependency Injection tool, StructureMap.

Setting up StructureMap

If you've never set up StructureMap in your MVC projects, you'll want to read this section; otherwise, skip to the next section.

The first thing we need to do is download the StructureMap.MVC5 NuGet package, which will add a DependencyInjection folder and a StructuremapMvc file to our app:

Inside the Dependency Resolution folder will be a file called DefaultRegistry.cs, which will initially look something like this:

namespace WebApiCacheDemo.Mvc.DependencyResolution {  
    using Caching;
    using StructureMap.Configuration.DSL;
    using StructureMap.Graph;

    public class DefaultRegistry : Registry {
        #region Constructors and Destructors
        public DefaultRegistry() {
            Scan(
                scan => {
                    scan.TheCallingAssembly();
                    scan.WithDefaultConventions();
                    scan.With(new ControllerConvention());
                });
        }
        #endregion
    }
}

The way StructureMap works is that it keeps instances of classes that need to be "injected" into other classes in a Container class, and uses these instances any time a particular interface is called for in another class. You'll see exactly what this means in the next section.

The Uncached Example

Let's build the uncached example first, and we can begin by setting up the MVC client. For this project we'll be using RestSharp (which I have also written about before) to consume the API responses, so be sure to download the NuGet package.

Because we're using Dependency Injection, we need our clients to be injectable into our controllers. For this reason, we will make both an interface and a class for our client, like so:

public interface ISampleClient : IRestClient  
{
    DateNumberObject GetSampleDateAndNumberUncached();
}

public class SampleClient : RestClient, ISampleClient  
{
    public SampleClient()
    {
        BaseUrl = new Uri("http://localhost:58566/");
    }

    public DateNumberObject GetSampleDateAndNumberUncached()
    {
        RestRequest request = new RestRequest("samples/date", Method.GET);
        var response = Execute<DateNumberObject>(request);
        return response.Data;
    }
}

Note that we don't need to register this client with StructureMap because the naming follows the standard conventions (ISampleClient maps to SampleClient).

Now we need our controller...

[RoutePrefix("Home")]
public class HomeController : Controller  
{
    private ISampleClient _sampleClient;

    public HomeController(ISampleClient sampleClient)
    {
        _sampleClient = sampleClient;
    }

    [HttpGet]
    [Route("Uncached")]
    [Route("")]
    [Route("~/")]
    public ActionResult Uncached()
    {
        var model = _sampleClient.GetSampleDateAndNumberUncached();
        return View(model);
    }
}

...which returns a view:

@model WebApiCacheDemo.Contracts.Samples.DateNumberObject
@{
    ViewBag.Title = "Uncached Date Sample";
}

<h2>Uncached Results</h2>  
<div class="row">  
    <span><strong>Current Date:</strong></span>
    @Model.CurrentDate
</div>  
<div class="row">  
    <span><strong>Random Number:</strong></span>
    @Model.RandomNumber
</div>  

When we run this, we can see that the view returns the newest date and time, as shown in this gif:

That's exactly what we would expect to see, of course. Now, we can get down to implementing a cache at the web layer for this.

The Cached Example

The first thing we need is our CacheService interface and implementation, which I totally stole from this StackOverflow answer:

public class InMemoryCache : ICacheService  
{
    public T GetOrSet<T>(string cacheKey, Func<T> getItemCallback) where T : class
    {
        T item = MemoryCache.Default.Get(cacheKey) as T;
        if (item == null)
        {
            item = getItemCallback();
            MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(30));
        }
        return item;
    }
}

public interface ICacheService  
{
    T GetOrSet<T>(string cacheKey, Func<T> getItemCallback) where T : class;
}

We also need our SampleClient class updated to use this cache service, like so:

public class SampleClient : RestClient, ISampleClient  
{
    private ICacheService _cache;
    public SampleClient(ICacheService cache)
    {
        _cache = cache;
        BaseUrl = new Uri("http://localhost:58566/");
    }

    public DateNumberObject GetSampleDateAndNumber()
    {
        return _cache.GetOrSet("SampleDateAndNumber", () => GetSampleDateAndNumberUncached());
    }

    public DateNumberObject GetSampleDateAndNumberUncached()
    {
        RestRequest request = new RestRequest("samples/date", Method.GET);
        var response = Execute<DateNumberObject>(request);
        return response.Data;
    }
}

NOTE: In my structure, I am intentionally implementing the cached and uncached operations as separate methods in the same client, so that either one can be used. This may or may not be the correct usage in your application.

Further, we need to update our controller:

[RoutePrefix("Home")]
public class HomeController : Controller  
{
    ...

    [HttpGet]
    [Route("Cached")]
    public ActionResult Cached()
    {
        var model = _sampleClient.GetSampleDateAndNumber();
        return View(model);
    }
}

The last step is to register the ICacheService implementing in StructureMap's DefaultRegistry.cs class:

namespace WebApiCacheDemo.Mvc.DependencyResolution {  
    ...

    public class DefaultRegistry : Registry {
        public DefaultRegistry() {
            ...
            var inMemoryCache = new InMemoryCache();
            For<ICacheService>().Use(inMemoryCache);
        }
    }
}

Now, when we run this sample, we will see the cached values for the date and number, as shown in the following gif:

Now we've successfully implemented our cache AND used Dependency Injection in the process!

Summary

With this structure, we've successfully implemented a caching layer into our MVC application, all while using StructureMap to provide Dependency Injection. This structure allows us to potentially swap cache providers (in case we, say, move to a database-located cache for server farms) without too much trouble, as well as injecting the cache service into our existing clients.

Don't forget to check out the sample project over on GitHub, and feel free to point out how you've used this implemention or where it can be improved in the comments.

Happy Coding!

The ASP.NET Web API 2 HTTP Message Lifecycle in 43 Easy Steps

Anyone who works with ASP.NET Web API should check out this poster that Microsoft created to explain the Request/Response Pipeline that Web API utilizes. It's amazing, and if you do any work in Web API you should check it out! Right now. Yes, seriously. Go ahead, I'll wait.

I love this poster, but in my opinion it doesn't do a good job of explaining the decision logic and ideas behind each step in the pipeline. Further, it doesn't explicitly tell you exactly how many things happen during this pipeline (answer: a surprisingly large number of things). In short: it's awesome, but it can be made more awesome by incorporating just a little more detail.

Here's what we're going to do in this post: using that poster, we're going to enumerate every single step involved in processing a request and receiving a response using ASP.NET Web API 2, and explain a little more about each piece of the pipeline and where we programmers can extend, change, or otherwise make more awesome this complex lifecycle. So let's get going and step through the ASP.NET Web API 2 Request Lifecycle in just 43 easy steps!

The 43 Steps

It all starts with IIS:

  1. IIS (or OWIN self-hosting) receives a request.
  2. The request is then passed to an instance of HttpServer.

  3. HttpServer is responsible for dispatching HttpRequestMessage objects.

  4. HttpRequestMessage provides strongly-typed access to the request.

  5. If one or more global instances of DelegatingHandler exist on the pipeline, the request is passed to it. The request arrives at the instances of DelegatingHandler in the order said instances were added to the pipeline.

  6. If the HttpRequestMessage passes the DelegatingHandler instances (or no such handler exists), then the request proceeds to the HttpRoutingDispatcher instance.

    • HttpRoutingDispatcher chooses which routing handler to call based on the matching route. If no such route exists (e.g. Route.Handler is null, as seen in the diagram) then the request proceeds directly to Step 10.

  7. If a Route Handler exists for the given route, the HttpRequestMessage is sent to that handler.

  8. It is possible to have instances of DelegatingHandler attached to individual routes. If such handlers exist, the request goes to them (in the order they were added to the pipeline).
  9. An instance of HttpMessageHandler then handles the request. If you provide a custom HttpMessageHandler, said handler can optionally return the request to the "main" path or to a custom end point.

  10. The request is received by an instance of HttpControllerDispatcher, which will route the request to the appropriate route as determined by the request's URL.

  11. The HttpControllerDispatcher selects the appropriate controller to route the request to.

  12. An instance of IHttpControllerSelector selects the appropriate HttpControllerDescriptor for the given HttpMessage.
  13. The IHttpControllerSelector calls an instance of IHttpControllerTypeResolver, which will finally call...
  14. ...an instance of IAssembliesResolver, which ultimately selects the appropriate controller and returns it to the HttpControllerDispatcher from Step 11.
    • NOTE: If you implement Dependency Injection, the IAssembliesResolver will be replaced by whatever container you register.
  15. Once the HttpControllerDispatcher has a reference to the appropriate controller, it calls the Create() method on an IHttpControllerActivator...
  16. ...which creates the actual controller and returns it to the Dispatcher. The dispatcher then sends the request into the Select Controller Action routine, as shown below.

  17. We now have an instance of ApiController which represents the actual controller class the request is routed to. Said instance calls the SelectAction() method on IHttpActionSelector...

  18. ...which returns an instance of HttpActionDescriptor representing the action that needs to be called.

  19. Once the pipeline has determined which action to route the request to, it executes any Authentication Filters which are inserted into the pipeline (either globally or local to the invoked action).

    • These filters allow you to authenticate requests to either individual actions, entire controllers, or globally throughout the application. Any filters which exist are executed in the order they are added to the pipeline (global filters first, then controller-level filters, then action-level filters).
  20. The request then proceeds to the [Authorization Filters] layer, where any Authorization Filters which exist are applied to the request.

    • Authorization Filters can optionally create their own response and send that back, rather than allowing the request to proceed through the pipeline. These filters are applied in the same manner as Authentication Filters (globally, controller-level, action-level). Note that Authorization Filters can only be used on the Request, not the Response, as it is assumed that if a Response exists, the user had the authorization to generate it.
  21. The request now enters the Model Binding process, which is shown in the next part of the main poster. Each parameter needed by the action can be bound to its value by one of three separate paths. Which path the binding system uses depends on where the value needed exists within the request.

  22. If data needed for an action parameter value exists in the entity body, Web API reads the body of the request; an instance of FormatterParameterBinding will invoke the appropriate formatter classes...

  23. ...which bind the values to a media type (using MediaTypeFormatter)...

  24. ...which results in a new complex type.

  25. If data needed for a parameter value exists in the URL or query string, said URL is passed into an instance of IModelBinder, which uses an IValueProvider to map values to a model (see Phil Haack's post about this topic for more info)....

  26. ...which results in a simple type.

  27. If a custom HttpParameterBinding exists, the system uses that custom binding to build the value...

  28. ...which results in any kind (simple or complex) of object being mappable (see Mike Stall's wonderful series on this topic).

  29. Now that the request is bound to a model, it is passed through any Action Filters which may exist in the pipeline (either globally or just for the action being invoked).

  30. Once the action filters are passed, the action itself is invoked, and the system waits for a response from it.

  31. If the action produces an exception AND an exception filter exists, the exception filter receives and processes the exception.

  32. If no exception occurred, the action produces an instance of HttpResponseMessage by running the Result Conversion subroutine, shown in the next screenshot.

  33. If the return type is already an HttpResponseMessage, we don't need to do any conversion, so pass the return on through.

  34. If the return type is void, .NET will return an HttpResponseMessage with the status 204 No Content.

  35. If the return type is an IHttpActionResult, call the method ExecuteAsync to create an HttpResponseMessage.

    • In any Web API method in which you use return Ok(); or return BadRequest(); or something similar, that return statement follows this process, rather than any of the other processes, since the return type of those actions is IHttpActionResult.
  36. For all other types, .NET will create an HttpResponseMessage and place the serialized value of the return in the body of that message.

  37. Once the HttpResponseMessage has been created, return it to the main pipeline.

  38. Pass the newly-created HttpResponseMessage through any AuthenticationFilters which may exist.

    • Remember that Authorization Filters cannot be used on Responses.

  39. The HttpResponseMessage flows through the HttpControllerDispatcher, which at this point probably won't do anything with it.

  40. The Response also flows through the HttpRoutingDispatcher, which again won't do anything with it.

  41. The Response now proceeds through any DelegatingHandlers that are set up to handle it. At this point, the DelegatingHandler objects can really only change the response being sent (e.g. intercept certain responses and change to the appropriate HTTP status).

  42. The final HttpResponseMessage is given to the HttpServer instance...

  43. ...which returns an Http response to the invoking client.

Tada! We've successfully walked through the entire Web API 2 request/response pipeline, and in only 43 easy steps!

Let me know if this kind of deep dive has been helpful to you, and feel free to share in the comments! Microsoft people and other experts, please chime in to let me know if I got something wrong; I intend for this post to be the definitive guide to the Web API 2 Request/Response Lifecycle, and you can't be definitive without being correct.

Happy Coding!

Getting All Valid Enum Values in ASP.NET Web API

One of the commenters on my blog posed an interesting question on my article about serializing enumerations in Web API:

A comment on my blog, asking

He wanted to know how someone who is querying a Web API might know what possible values a given enumeration has. I didn't answer that in the post he commented on, so I'll do that now. How do we tell consumers what possible values an enumeration in a Web API app has?

Let's say we have the following enums:

public enum AddressType  
{
    Physical,
    Mailing,
    Shipping
}

public enum AccessLevel  
{
    Administrator,
    ReadWrite,
    ReadOnly
}

We want to expose a query which returns these values for each enumeration. To do that, let's create a class for EnumValue:

public class EnumValue  
{
    public string Name { get; set; }
    public int Value { get; set; }
}

It's a pretty generic class, to be sure, but since all enumerations are is a name and a value it serves our purposes well enough.

The trick now is to create an extension which uses Reflection to get all the names for the given enum. In fact, we can even make that method generic, so it can be used for any enumeration at all.

public static class EnumExtensions  
{
    public static List<EnumValue> GetValues<T>()
    {
        List<EnumValue> values = new List<EnumValue>();
        foreach (var itemType in Enum.GetValues(typeof(T)))
        {
            //For each value of this enumeration, add a new EnumValue instance
            values.Add(new EnumValue()
            {
                Name = Enum.GetName(typeof(T), itemType), 
                Value = (int)itemType
            });
        }
        return values;
    }
}

Finally, we can use Web API methods that call this extension:

public class HomeController : ApiController  
{
    [HttpGet]
    [Route("accesslevels/all")]
    public IHttpActionResult GetAccessLevels()
    {
        return Ok(EnumExtensions.GetValues<AccessLevel>());
    }

    [HttpGet]
    [Route("addresstypes/all")]
    public IHttpActionResult GetAddressTypes()
    {
        return Ok(EnumExtensions.GetValues<AddressType>());
    }
}

When we call this method using Postman, we now get an appropriate response code (200 OK) and the data we were looking for. Here's the address types:

A Postman response, showing the three possible values for the enumeration AddressType

And here's the access levels:

A Postman response, showing the three possible values for the enumeration AccessLevel

Of course, this is just one of many possible solutions to this particular problem. I like this method because it's generic and reusable for all enumerations, but if you find a better method, please feel free to share in the comments!

That's all there is to it! Now any consumer can hit these methods and know exactly what values can be used for the AccessLevel and AddressType enumerations!

I also have a repository over on GitHub which stores the sample code for this post. Check it out!

Happy Coding!