The first thing I would do is read Middleware - Asp.Net Documentation
This will help understand how middleware is used and the pracitices to follow to implement your own custom middleware.
taken directly from docs
Middleware are software components that are assembled into an
application pipeline to handle requests and responses. Each component
chooses whether to pass the request on to the next component in the
pipeline, and can perform certain actions before and after the next
component is invoked in the pipeline. Request delegates are used to
build the request pipeline. The request delegates handle each HTTP
request.
Now as this states it allows the components to handle the requests and responses. The middle ware is executed in the order it is added to the application middleware collection.
app.UseStaticFiles();
adds the middlware to handle static files (images, css, scripts etc).
Now say you wish to add your own handling in the pipeline you can create a middleware class as a sample below.
public class GenericMiddleware
{
public GenericMiddleware(RequestDelegate next)
{
_next = next;
}
readonly RequestDelegate _next;
public async Task Invoke(HttpContext context, IHostingEnvironment hostingEnviroment)
{
//do something
await _next.Invoke(context);
}
}
There are a few interesting points here. First off the constructor takes a RequestDelegate
which is essentially (but not exactly) the next middleware object that will be invoked.
Next we implement our own Invoke
method. This method should take the HttpContext
as a paramater and will also allow for additional dependencies to be injected from the IoC container (in my example the IHostingEnvironment
instance).
This method then executes the code it needs to execute and then calls await _next.Invoke(context);
which executes the RequestDelegate
to call the next middleware class.
Now to add this to the application middle ware you can simply call
app.UseMiddleware<GenericMiddleware>();
in your Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
method in the startup.cs
file.
Or create a simple extension method as.
public static class GenericMiddlewareExtensions
{
public static IApplicationBuilder UseGenericMiddleware(this IApplicationBuilder app)
{
app.UseMiddleware<GenericMiddleware>();
return app;
}
}
Which is then called app.UseGenericMiddleware();
Now how and why you implement your own middleware is up to you. However as stated it is up to the middleware to call the next RequestDelegate
if it doesnt then it stops the request.
Here is an example in one of my projects that checks to see if the database is installed. If it isnt redirects the request back to the installation page.
public class InstallationMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
public InstallationMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
{
_next = next;
_logger = loggerFactory.CreateLogger<InstallationMiddleware>();
}
public async Task Invoke(HttpContext context)
{
_logger.LogInformation("Handling request: " + context.Request.Path);
if (context != null && !DatabaseHelper.IsDatabaseInstalled())
{
if (!context.Request.Path.ToString().ToLowerInvariant().StartsWith("/installation"))
{
context.Response.Redirect("/installation");
return;
}
}
await _next.Invoke(context);
_logger.LogInformation("Finished handling request.");
}
}
As you can see if !DatabaseHelper.IsDatabaseInstalled()
we redirect the response but dont invoke the _next
RequestDelegate
.
Again the documentation speaks for itself.