Take advantage of message handlers to execute cross cutting concerns earlier in the Web API life cycle Message handlers in Web API provide you the opportunity to process, edit, or decline an incoming request before it reaches the HttpControllerDispatcher. Message handlers are executed much earlier in the request processing pipeline, hence they are a great place to implement cross cutting concerns in Web API. Implementing a custom message handler All message handlers derive from the class HttpMessageHandler. To build your own message handler, you should extend the DelegatingHandler class. Note that the DelegatingHandler class in turn derives from the HttpMessageHandler class. Consider the following Web API controller. public class DefaultController : ApiController { public HttpResponseMessage Get() { return Request.CreateResponse(HttpStatusCode.OK, "Inside the Default Web API Controller..."); } } To create a message handler, you need to extend the DelegatingHandler class and override the SendAsync method. public class IDGHandler : DelegatingHandler { protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { return base.SendAsync(request, cancellationToken); } } The Web API request processing pipeline includes a few built-in message handlers. These include the following: HttpServer — this is used to retrieve the request from the host HttpRoutingDispatcher — this is used to dispatch the request based on the route configured HttpControllerDispatcher — this is used to send the request to the respective controller You can add message handlers to the pipeline to perform one or more of the following operations. Perform authentication and authorization Logging the incoming requests and the outgoing responses Add response headers to the response objects Read or modify the request headers The following code snippet shows how you can implement a simple message handler in Web API. public class IDGHandler : DelegatingHandler { protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent("Inside the IDG message handler...") }; var task = new TaskCompletionSource<HttpResponseMessage>(); task.SetResult(response); return await task.Task; } } The IDG message handler doesn’t process the request message — it creates response message and then returns it. You can also call the base version of the SendAsync method if you wouldn’t like to do anything with the incoming request as shown in the code listing below. public class IDGHandler : DelegatingHandler { protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { return await base.SendAsync(request, cancellationToken); } } You can also write code to log the Http requests and the responses that go out in the SendAsync method. To execute the Web API you can use a test method like the one given below. [TestMethod] public void WebAPIControllerTest() { HttpClient client = new HttpClient(); var result = client.GetAsync(new Uri("http://localhost/IDG/api/default/")).Result; string responseMessage = result.Content.ReadAsStringAsync().Result; Assert.IsTrue(result.IsSuccessStatusCode); } When you execute the test method, the message “Inside the Default Web API Controller…” is returned as a response message and the test passes. Oh! We did create a message handler, but we are yet to register it to the message handling pipeline. You would now need to let the Web API infrastructure know where your custom handler exists. To do this, you should register your custom handler in the pipeline. You can register the IDG custom message handler we just created in the Register method of the WebApiConfig class as shown below. public static void Register(HttpConfiguration config) { GlobalConfiguration.Configuration.MessageHandlers.Add(new IDGHandler()); } When you execute the test method again, the text message “Inside the logging message handler…” is returned as a response message and the test passes. Note that you can also register multiple message handlers to the message handling pipeline as shown in the code snippet below. public static void Register(HttpConfiguration config) { GlobalConfiguration.Configuration.MessageHandlers.Add(new MessageHandlerA()); GlobalConfiguration.Configuration.MessageHandlers.Add(new MessageHandlerB()); GlobalConfiguration.Configuration.MessageHandlers.Add(new MessageHandlerC()); } The message handlers would be executed in the order in which they have been added to the pipeline and the response would be returned in the reverse order. In other words, at the time of the incoming request, the message handlers are executed in the order in which they are registered. During the outgoing response, the process is just reversed. So, the message handlers are executed in the reverse order of their registration to the pipeline. You can also implement a message handler that inspects the incoming request and checks if the request contains a valid api key. If the api key is not present or is not valid, it returns an appropriate error message. The following code listing shows how you can do this — I’m leaving it to you to write the code to validate the api key anyway. protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { string key = HttpUtility.ParseQueryString(request.RequestUri.Query).Get("key"); string errorMessage = "You need to specify the api key to access the Web API."; try { if (!string.IsNullOrWhiteSpace(key)) { return base.SendAsync(request, cancellationToken); } else { HttpResponseMessage response = request.CreateErrorResponse(HttpStatusCode.Forbidden, errorMessage); throw new HttpResponseException(response); } } catch { HttpResponseMessage response = request.CreateErrorResponse(HttpStatusCode.InternalServerError, "An unexpected error occured..."); throw new HttpResponseException(response); } } Related content feature 14 great preprocessors for developers who love to code Sometimes it seems like the rules of programming are designed to make coding a chore. Here are 14 ways preprocessors can help make software development fun again. By Peter Wayner Nov 18, 2024 10 mins Development Tools Software Development feature Designing the APIs that accidentally power businesses Well-designed APIs, even those often-neglected internal APIs, make developers more productive and businesses more agile. By Jean Yang Nov 18, 2024 6 mins APIs Software Development news Spin 3.0 supports polyglot development using Wasm components Fermyon’s open source framework for building server-side WebAssembly apps allows developers to compose apps from components created with different languages. By Paul Krill Nov 18, 2024 2 mins Microservices Serverless Computing Development Libraries and Frameworks news Go language evolving for future hardware, AI workloads The Go team is working to adapt Go to large multicore systems, the latest hardware instructions, and the needs of developers of large-scale AI systems. By Paul Krill Nov 15, 2024 3 mins Google Go Generative AI Programming Languages Resources Videos