On my previous post I ended up with a simple Hello World web application. The application configuration simply registered a callback to handle all the requests and write something to the response. I’d like to revisit this in more detail.
public void Configure(IApplicationBuilder app)
{
app.Run(ctx => ctx.Response.WriteAsync("Hello ASP.NET 5 world! Time: " + DateTime.Now));
}
Let’s start by IApplicationBuilder. This interface – which was IAppBuilder on Katana – is a means of registering components (middlewares) that participate on request processing. You do so by invoking its Use method:
IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);
The method’s signature can be a bit confusing at first. In order to understand it, lets look into RequestDelegate:
public delegate Task RequestDelegate(HttpContext context);
This delegate represents the handling of a request. It’s a function that gets a context and returns a Task that completes when the request has been processed; it corresponds to OWIN’s AppFunc. Did you notice HttpContext? This isn’t System.Web’s infamous class; it’s a new one with the same name and similar function, resulting from Katana’s IOwinContext.
Back to the Use method, we can say that it gets a function that maps one request handler to another. In other words, whatever function that is, it is a means of composing around an existing request handler. This is similar to DelegatingHandlers on ASP.NET Web API and has some similarities with System.Web’s IHttpModule. It’s worth pointing that the Run method on the example above is just an extension method that invokes Use with a constant RequestDelegate. So, let’s do a simple middleware:
public class GotchaMiddleware
{
public RequestDelegate Process(RequestDelegate next)
{
return async httpContext =>
{
await next(httpContext);
await httpContext.Response.WriteAsync(" GOTCHA!");
};
}
}
And register it on the pipeline:
public void Configure(IApplicationBuilder app)
{
app.Use(new GotchaMiddleware().Process);
app.Run(ctx => ctx.Response.WriteAsync("Hello ASP.NET 5 world! Time: " + DateTime.Now));
}
Note how the middleware has a method that matches the Use method signature. Running the application from the command line again, we get:
Hello ASP.NET 5 world! Time: 07/03/2015 00:26:01 GOTCHA!
ASP.NET includes different middlewares, such as one for serving static files. MVC 6 itself is plugged in as a middleware. Typically, each middleware defines an extension method for IApplicationBuilder to register itself on the pipeline. For instance, we can register the static file handler by adding a dependency on the corresponding NuGet package to the project.json file:
{
"dependencies": {
"Microsoft.AspNet.StaticFiles" : "1.0.0-beta3",
...
},
...
}
And invoking the UseStaticFiles extensions method:
public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles();
// ...
}
Note the pay-for-play philosophy: we needed to serve static files, so we added a new package.
On the following post I’ll end this Hello World set by adding a simple MVC controller.