ASP.NET WebForm or MVC applications rely on
global.asax to process HTTP request pipelines. Within
global.asax, each HTTP request goes through declared HTTP modules and HTTP handlers based on events. On the other hands, ASP.NET Core applications use OWIN middlewares. Actually, those middlewares now take care of what HTTP modules and HTTP handlers do. In this post, we are going to implement an HTTP request handler on a ASP.NET Core application.
Why Does It Matter?
Single Page Applications (SPA) is now a trend of web application development. SPA only contains UI logics and all other business logics are processed by calling APIs. Calling APIs through AJAX is not a problem. For example, if we use jQuery, typical AJAX call will look like:
If we need an API key for the call, the AJAX call might look like:
The main differences between HTTP modules and HTTP handler are:
- HTTP modules process requests and pass them to another modules.
- HTTP handlers process requests and return their responses to browsers.
As middlewares in ASP.NET Core take care of both HTTP modules and HTTP handlers, implementation becomes a lot easier and simpler. Here’s a basic middleware looking like:
And, in order to easily use this middleware at
Startup.cs, we can just create an extension method like:
And this extension method is placed into the
Configure method of
Within the OWIN pipeline, middlewares are invoked by an order where they are declared. Therefore,
MyMiddleware is invoked after the previous middleware then passes
HttpContext instance to the next middleware for further processing. Here’s the clue. If we want to implement the middleware as an HTTP handler, we simply don’t run the
this._next.Invoke(context) method so that all HTTP requests complete processing at this point. Let’s make a working example.
All codes used in this post here can be found at: https://github.com/devkimchi/ASP.NET-Core-HTTP-Request-Handler-Sample
HTTP Request Header Handler Middleware
We don’t need MVC controller for our ASP.NET Core application any more because the middleware takes all AJAX requests, put some additional header and pass the requests to API server. Therefore, we can simply remove MVC middleware from the
Startup.cs and add
HttpRequestHeaderHandlerMiddleware into it.
As we can see above, it processes the request and sends
HttpContext back with response. This perfectly works as API proxy, without needing controllers. Let’s go further.
Middleware with Options Pattern
The potential problem of
HttpRequestHeaderHandlerMiddleware written above is that all custom headers are hard-coded. If we add/update/delete header values, we have to update the code. Fortunately, ASP.NET Core provides Options Pattern. This is basically for dependency injection for configuration values that are declared within
appsettings.json or environment variables. We can use this pattern for our middleware implementation with additional extension methods.
HttpRequestHeaderHandlerMiddlewareOptons and this will be injected to
HttpRequestHeaderHandlerMiddleware by calling
Options.Create(options) method, which creates
IOptions instance. Here’s another extension method to declare options with lambda expressions.
Once it’s done, the
HttpRequestHeaderHandlerMiddleware needs to be updated to accept the options instance as a parameter.
Now we can use options within our middleware. Those options can be defined within
appsettings.json file, populated as a strongly-typed instance and injected to the middleware like:
So far, we have implemented a middleware as an API proxy to capture all HTTP requests, put extra header information into it and process it. With this approach, our SPA backed by ASP.NET Core would be much simpler and light-weighted.