Posts Tagged 'ASP.NET Web API'

Processing Messages in a Self-Hosted Web API Service

In an earlier post, I showed how to host an ASP.NET Web API service on a server without IIS. In that post, I suggested that the most interesting object used in the self-hosting process is the HttpSelfHostConfiguration object–that’s the object that allows you to configure your service. In that last post, for instance, I used the HttpSelfHostConfiguration object to specify the service’s URL and routing rules. But that’s just a taste of the configuration object’s power: you can also use the HttpSelfHostConfiguration object to insert handlers into the Web API’s processing pipeline to centralize  pre- or post-processing on messages sent to and from your service (you can insert message handlers when hosting a Web API service in IIS, also).

You can add as many handlers as you want to the Web API processing pipeline: each handler’s output is automatically passed to the next handler in the pipeline. The handlers are processed in reverse order to the way that you add them to the pipeline (i.e. the handler you add first is the handler “closest” to your service and gets inbound messages after all the other handlers you add have processed the message; for the same reason, the first handler you add will see any outbound messages as soon as they leave the service and before any of the handlers you’ve added to the pipeline see the message).

As an example, let’s say that you don’t want the services your hosting to process any messages with the HTTP Delete verb because you don’t allow deletes: you simply mark records as deleted and stop returning those records to the client. All requests to delete records should, you’ve decided, be sent with the HTTP Put verb because they’re actually updates to the record’s Deleted field. You could, of course, simply not provide a Delete method in your service–that would generate a return error message of “The requested resource does not support http method ‘GET’.” should someone send your service a Delete request. However, you may want to send a response that’s more informative to any client using the Delete verb (alternatively, you might want to log these Delete requests). You could add a Delete method to each of your services that performed those actions but it would be a better practice to centralize that site-wide utility code in one place: a message handler.

Adding Handlers

The first step is to add your message handler to the configuration object’s Handlers collection before passing the configuration object to the host. This code assumes that the handler is called PHVHandler:

hcfg = new HttpSelfHostConfiguration("http://www.phvis.com");
PHVHandler hndlr = new PHVHandler();
hcfg.MessageHandlers.Add(hndlr);

If you want, you can limit a handler to processing only those requests for a single route. In that case, you pass the handler as the fifth parameter to the MapHttpRoute method (right after specifying any constraints on the route). This example adds a handler that will be used only for requests with “Customers” in the URL:

hcfg = new HttpSelfHostConfiguration("http://www.phvis.com");
PHVHandler hndlr = new PHVHandler();
hcfg.Routes.MapHttpRoute("HandledTemplate",
                         "Customers",
                         new { controller = "CustomerManagement" },
                         null,
                         hndlr);

Creating a Handler

A handler is a class that inherits from DelegatingHandler (you’ll need using statements for  System.Net and System.Net.Http for the following code to work). Once you’ve added the class you must override its SendAsync method. The SendAsync method is called automatically by the Web API for every request to your service. The method is passed an HttpRequestMessage that holds all the data related to the request to your service (and a CancellationToken, which I’ll ignore in this post):

class PHVHandler: DelegatingHandler
{
 protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
 {

If the PHVHandler is the last one added to the pipeline, it will get the HttpRequestMessage before any other handler has modified it; if other handlers were add to the configuration object after this handler, then the HttpRequestMessage will show the results of any modifications that handlers earlier in the pipeline have made. If you’re doing test driven development, by the way, you can test your handler by instantiating an HttpRequestMessage object, setting its properties, and passing it your method–something that’s virtually impossible to do with the ASP.NET HttpContext object.

Your message processing code goes in the SendAsync method. The following code checks to see if the Method (the HTTP verb) associated with this request is a Delete and, if so, stops the message from proceeding up the pipeline. To short-circuit processing and return a message to the client you need to create two objects: an HttpResponseMessage object, specifying a return value with some content (Forbidden and a string, , in this case) and a TaskCompletionSource (because these are asynchronous methods, Task-related objects are used to wrap most of the method’s inputs and outputs). With the two objects created, use the TaskCompletionSource object’s SetResult method to pass the HttpResponseMessage to the TaskCompletionSource. Once the TaskCompletionSource is configured, you can return it which is what this code does:

if (request.Method == HttpMethod.Delete)
{
  HttpResponseMessage rsp = new HttpResponseMessage(HttpStatusCode.Forbidden);
  rsp.Content =new StringContent("Deletes not accepted--use Put"); 
  TaskCompletionSource<HttpResponseMessage> tkc = new TaskCompletionSource<HttpResponseMessage>();
  tkc.SetResult(rsp);
  return tkc.Task;
}

However, if the message sent to your service isn’t using the Delete verb, it should be passed on to your service (or the next handler in the pipeline) for processing. To pass the message on up the pipeline, call the base version of the SendAsync method, passing the parameters you originally received in your version of the method:

return base.SendAsync(request, cancellationToken);

Calling the SendAsync method puts the message in the pipeline to go to the service. When your service finishes processing the message, the service will create a response message and send that back down through the pipeline. The object returned by the SendAsync method  in the previous code is the outbound response message created by the service (and, possibly, modified by any message handlers that the message has already passed through). You must return the result of the SendAsync method from your method to allow the message to continue through the pipeline back to the client. While it’s not obvious in this code, the SendAsync method is returning a Task object holding an HttpResponseMessage containing the service’s output message (again, the Task object is required to support asynchronous processing).

Altering the Inbound Message

However, a message handler can do more than just terminate processing. You can use a message handler to alter the message on its way up the pipeline. Rather than terminate processing when you see a Delete verb, for instance, you could change all Delete requests to Puts and let the messages continue on up the pipeline. As in the previous example, the following code first checks the inbound message to see if it’s a Delete. If it is, the code then alters the message before sending it on through the pipeline using the SendAsync method. The SendAsync method will (eventually, since its an asynchronous method) return the Task object holding the client’s HttpResponseMessage which you must return from your method:

if (request.Method == HttpMethod.Put)
{
 request.Method = HttpMethod.Put;
 return base.SendAsync(request, cancellationToken);
}

Altering the Outbound Message

Because the message passes through your handler on the way back to the client, you can also process the outbound message after it leaves the service and before it gets back to the client. This means waiting for your call to the base.SendAsync method to complete so that you can catch the outbound message–not a completely trivial task because SendAsync is an asynchronous method. If you’re working in .NET 4.0 then you’ll need to use the ContinueWith method to wait for the Task object returned from the SendAsync method. The ContinueWith method passes the Task returned from SendAsync to a lamba expression of your design. In that lambda expression you’ll typically want to extract the HttpResponseMessage from the Task and modify the message before letting the message continue through the pipeline. This example sets the StatusCode on the message to indicate that the request needs to be upgraded before returning the response (the Web API will take of wrapping the response in a Task):

return base.SendAsync(request, cancellationToken).ContinueWith((t) =>
{
  HttpResponseMessage rsp = t.Result;
  rsp.StatusCode = HttpStatusCode.UpgradeRequired;
  return rsp;
}

In .NET 4.5 you can take advantage of the await keyword which simplifies working with asynchronous methods–your code hardly looks asynchronous at all! First, you must add the async keyword to your method’s declaration:

class PHVHandler: DelegatingHandler
{
 async protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
 {

With the async keyword in place, you can use the await keyword to catch the output of the SendAsync method when it’s finally handed back to you. This example, as before, sets the StatusCode on the response message before returning the response:

HttpResponseMessage rsp = await base.SendAsync(request, cancellationToken);
rsp.StatusCode = HttpStatusCode.UpgradeRequired;
return rsp;

As you may have noticed, one of the nice features of self-hosting is that all your configuration code goes in one place: In the Windows Service that you’ll use to host your Web API service–which I find sort of convenient. I referred to Learning Tree’s course on creating .NET services (including the ASP.NET Web API) in my last post but I should also have mentioned Learning Tree’s course on deciding what services you need and how they should work together, Service-Oriented Architecture (SOA): A Comprehensive Hands-On Introduction (especially because I wrote the course).

Peter Vogel

Creating Your Own Host for a Web API Service

Kevin Rattan has done several posts on Microsoft’s ASP.NET Web API (you can find all of this blog’s Web API posts here) which have done a great job of showing (among other things) how the Web API is different from WCF. The Web API is designed from the ground up to leverage the HTTP protocol, for instance, which makes it easy to create RESTful services. But, like WCF, it’s ridiculously easy to add a Web API controller to either an ASP.NET or ASP.NET MVC application. And, also, like WCF you can create your own host for your Web API services.

Which, of course, raises the question: If it’s so easy to add a Web API service to a website why would you want to create your own host? Hosting your own Web API services is obviously a niche solution: most of the time you’ll want to leverage IIS as your service’s host. However, creating your own host allows you to control  your service in ways that might be difficult to implement if your service is part of a website hosted by IIS. For instance, with your own host the URL for your service is completely under your control (well, except for the server’s name) and isn’t constrained by the name of the website the service is part of. Managing your host is also independent of IIS management: You may want to self-host because you find that working with your Web Administrator is even less fun than working with your DBA–creating your own Web API host lets you bypass that person.

Configuring the Host Project

If you are going to create your own host, you should create the host as a Windows Service. That isn’t essential: practically any .NET project type can be used to host a Web API service. If you wanted your host to have a user interface that you could interact with then creating your host as a WPF or WinForms project would meet that goal more easily than a Windows Service project would. However, creating your host as a Windows Service is easy to do (as long as you don’t need the UI) and allows you to manage your host from the Services node in the Windows Management Console. For instance, by setting your Windows Service’s start mode as Automatic, your host will start up with the computer it’s running on and shut down with it.

The first step in creating your Web API host is to create a new Windows Service project in Visual Studio (File | New | Project | Windows | Windows Service).  Once the project is created, right mouse click on it in Solution Explorer and select Manage NuGet Packages to retrieve the Web API package  you need. Once in NuGet, search in the online section for “aspnet.webapi” to find all (and only) the Web API packages. From the packages listed, the one that you need so that you can create your own host is called Microsoft ASP.NET Web API Self Host (do not select Microsoft ASP.NET Web API Web Host). Click on the package, click the Install button, accept the licensing terms and you project is almost ready to write some code–there’s just two things left to do before you can start writing code.

First, add a reference to System.Web.Routing to your project–you’ll need this later to configure your service. You’ll also want your service to have a more meaningful name than the default Service1. Delete the default Service1 in your project, right-mouse click on your project in Solution Explorer, and select Add | New Item | General | Windows Service. Give your service a meaningful name (I used “PHVService”) and click the Add button. Now you’re ready to write code.

Writing the Windows Service

A Windows Service initially displays the Service’s graphical designer which you can ignore–open its code file by double clicking on the designer. There are two key events in a Windows Service’s life: when it starts and when it stops. The methods associated with these events (OnStart and OnStop) are, typically, where you’ll want to load your host and where you’ll want to shut your host down. I’m going to create my host in the OnStart event and shut it down in the OnStep event (for the following code to work, you’ll need to add using statements for System.Web.Http.SelfHost and System.Web.Http to Service’s code file). Since that means that my HttpSelfHostServer must be available in both methods, I declare it at the class level:

 partial class PHVService : ServiceBase
{
  private HttpSelfHostServer shs;

First, create an HttpSelfHostConfiguration object that will specify how your service behaves. When you instantiate the HttpSelfHostConfiguration object pass it the endpoint for your service (the initial part of the endpoint will have to be the name of the computer that your service is running on–the rest is up to you):

 protected override void OnStart(string[] args)
{
  HttpSelfHostConfiguration hcfg =
    new HttpSelfHostConfiguration("http://phvis.com/MyServices");

The configuration object gives you the ability to configure a great many things about your service–all but one of which is optional. You must set up a route to the controller that makes up your service. This example sets up the simplest possible route (“http://phvis.com/MyServices/Customers&#8221;) and ties it to a controller called CustomerManagementController:

hcfg.Routes.MapHttpRoute("CustomerServiceRoute",
                         "Customers",
                         new { controller = "CustomerManagement" });

Finally, you’ll want to open your host. Create your HttpSelfHostServer, passing your configuration object,and then call the host’s OpenAsync method:

shs = new HttpSelfHostServer(hcfg);
shs.OpenAsync();

The OnStop method is simpler. When the service is shut down (as part of the server shutting down, for instance) this method will be called automatically. In the OnStop method, you want to call the HttpSelfHostServer object’s CloseAsync method to start shutting down your host. However, I don’t think it would be a good practice to let the service continue to the end of its OnStop method until your host really has shut down. So, in this code, I’ve used the Await method to hold execution until the CloseAysnc method completes (I also call the host’s Dispose method just to free up any remaining resources that the host might be controlling):

protected override void OnStop()
{
  shs.CloseAsync().Wait();
  shs.Dispose();
}

There’s still stuff to do. It’s still your responsibility to create the Web API controller referenced in the route you created. You should also create a setup project you can use to install your Windows Service on its server. And, of course, while I’ve shown you how to create your own host, I haven’t shown you how you can configure your Web API service. That’s another post.

Learning Tree has an excellent course about creating services in .NET that covers the ASP.NET Web API: WCF and Web API .NET Services: A Comprehensive Hands-On Introduction.

Peter Vogel


Learning Tree International

.NET & Visual Studio Courses

Learning Tree offers over 210 IT training and Management courses, including a full curriculum of .NET training courses.

Free White Papers

Questions on current IT or Management topics? Access our Complete Online Resource Library of over 65 White Papers, Articles and Podcasts

Enter your email address to subscribe to this blog and receive notifications of new posts by e-mail.

Join 29 other followers

Follow Learning Tree on Twitter

Archives

Do you need a customized .NET training solution delivered at your facility?

Last year Learning Tree held nearly 2,500 on-site training events worldwide. To find out more about hosting one at your location, click here for a free consultation.
Live, online training

%d bloggers like this: