In this chapter, you will add middleware that handles HTTP requests, like how the application behaves if there is an error. One key aspect of the middleware is to perform user authentication and authorization.
By the end of this chapter you will have built a middleware pipeline for a MVC application.
Let’s have a look at how middleware works and what it is used for.
When an HTTP request comes to the server, it is the middleware components that handle that request.
Each piece of middleware in ASP.NET is an object with a very limited, specific, and focused role. This means that you will have to add many middleware components for an application to work properly.
The following example illustrates what can happen when an HTTP POST request to a URL, ending with /reviews, reaches the server.
Logging is a separate middleware component that you might want to use to log information about every incoming HTTP request. It can see every piece of data, such as the headers, the query string, cookies, and access tokens. Not only can it read data from the request, it can also change information about it, and/or stop processing the request.
The most likely scenario with a logger is that it will log information and pass the processing onto the next middleware component in the pipeline.
This mean that middleware is a series of components executed in order.
The next middleware component might be an authorizer that can look at access tokens or cookies to determine if the request will proceed. If the request doesn’t have the correct credentials, the authorizer middleware component can respond with an HTTP error code or redirect the user to a login page.
If the request is authorized, it will be passed to the next middleware component, which might be a routing component. The router will look at the URL to determine where to go next, by looking in the application for something that can respond. This could be a method on a class returning a JSON, XML, or HTML page for instance. If it can’t find anything that can respond, the component could throw a 404 Not Found error.
Let’s say that it found an HTML page to respond; then the pipeline starts to call all the middleware components in reverse order, passing along the HTML. When the response ultimately reaches the first component, which is the logger in our example, it might log the time the request took and then allow the response to go back over the network to the client’s browser.
This is what middleware is, a way to configure how the application should behave. A series of components that handle specific, narrow tasks, such as handle errors, serve up static files and send HTTP requests to the MVC framework. This will make it possible for you to build the example video application.
This book will not go into the nitty-gritty of middleware – only the basics that you need to build a MVC application.
The IApplicationBuilder interface injected into the Startup class’s Configure method is used when setting up the middleware pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IMessageService msg)
{
if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
app.Run(async (context) =>
{
await context.Response.WriteAsync(msg.GetMessage());
});
}
To add middleware, you call extension methods on the app parameter, which contains the dependency-injected object for the IApplicationBuilder interface. Two middleware components are already defined in the Configure method.
The UseDeveloperExceptionPage middleware component will display a pretty error page to the developer, but not the user; you can see that it is encapsulated inside an if-block that checks if the environment variable is set to the development environment.
The UseDeveloperExceptionPage middleware component then calls the Run middleware component that is used to process every response. Run is not frequently used because it is a terminal piece of middleware, which means that it is the end of the pipeline. No middleware component added after the Run component will execute, because Run doesn’t call into any other middleware components.
app.Run(async (context) =>
{
await context.Response.WriteAsync(msg.GetMessage());
});
By using the context object passed into the Run method, you can find out anything about the request through its Request object –the header information, for instance. It will also have access to a Response object, which currently is used to print out a string.
In the previous chapter, you called the GetMessage method on the message service inside the Run method.
Most middleware components will be added by calling a method beginning with Use on the app object, such as app.UseDeveloperExceptionPage.
As you can see, there are several middleware components available out of the box using the app object. You can add more middleware components by installing NuGet packages containing middleware.
Let’s have a look at how exception messages are handled by the pipeline. As previously mentioned the app.UseDeveloperExceptionPage middleware is in place to help the developer with any exceptions that might occur. To test this behavior, you can add a throw statement at the top of the Run-block and refresh the application in the browser.
app.Run(async (context) =>
{
throw new Exception("Fake Exception!");
await context.Response.WriteAsync(msg.GetMessage());
});
using System;
Now let’s see what happens if you change the environment variable to Production and refresh the page.
Now let’s see what happens if we comment out the app.UseDeveloperExceptionPage middleware.
//app.UseDeveloperExceptionPage();
throw new Exception("Fake Exception!");
You can use the IHostingEnvironment object, passed in through dependency injection, to find out information about the environment. You have already used an if statement to determine if the environment variable is set to Development, if it is, a pretty error page will be displayed. You can also use it to find out the absolute path to the wwwroot directory in the project with the WebRootPath property.
A feature that nearly all web applications need is the ability to serve up static files, such as JSON, CSS, and HTML files. To allow ASP.NET to serve up files, you must add a new middleware component that is called with the UseStaticFiles method, located in the Microsoft
.AspNetCore.StaticFiles NuGet package, which is installed with the default Microsoft
.AspNetCore.App NuGet package.
Without the UseStaticFiles middleware component, the application will display the message from the Run middleware.
Let’s add an HTML file to the wwwroot folder and see what happens, and why. Static files must be added to the wwwroot folder for ASP.NET to find them.
The reason why the message Hello, from configuration is displayed is that there currently is no middleware that can serve up the static file. Instead the message in the Run middleware, which is accessible, will be displayed.
Let’s fix this by adding a new middleware located in the Microsoft.AspNetCore.StaticFiles NuGet package, which is installed by deafult.
When the UseStaticFiles method is called on the app object, ASP.NET will look in the wwwroot folder for the desired file. If a suitable file is found, the next piece of middleware will not be called.
app.UseStaticFiles();
The complete code for the Configure method:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IMessageService msg)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.Run(async (context) =>
{
await context.Response.WriteAsync(msg.GetMessage());
});
}
The last thing you will do in this chapter is to set up the ASP.NET MVC middleware and add a simple controller to test that it works.
The NuGet Microsoft.AspNetCore.Mvc package, which is installed by default, contains the MVC middleware that you will add to the HTTP pipeline and the MVC service that you will add to the services collection.
You will add a controller class with an Index action method that can be requested from the browser. In ASP.NET MVC, static HTML files, such as index.html, are not used. Instead views are usually used to serve up the HTML, JavaScript, and CSS content to the user. You will learn more about MVC in the next chapter. For now, let’s look at a simple example.
public class
HomeController : Controller
{
}
public string Index()
{
return "Hello, from the controller!";
}
app.UseMvcWithDefaultRoute();
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
...
}
The complete code in the ConfigureServices method:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSingleton<IMessageService,
ConfigurationMessageService>();
}
The complete code in the Configure method:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IMessageService msg)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
app.Run(async (context) =>
{
await context.Response.WriteAsync(msg.GetMessage());
});
}
In this chapter, you learned how to configure middleware in the Configure method of the Startup class.
The application now has several middleware components, including a developer error page and MVC. The MVC middleware can forward a request to an action method in a controller class to serve up content.
In the next chapter, you will learn more about controllers, and that you can use many different controllers in the same application, and how to route the HTTP requests to the appropriate one.
You will also create controller actions that return HTML, instead of just a string, as in the previous example.
Join our mailing list to receive the latest news and updates from our team.
Don't worry, your information will not be shared.
50% Complete
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.