Hello ASP.NET 5 World – Part III

In the previous post I improved the hello world example to include the static files middleware. In this post I’ll wrap up this series by adding MVC. The first thing is to add the corresponding package. This can be done on the command line:

kpm install Microsoft.AspNet.Mvc 6.0.0-beta3

As the static file middleware, MCV includes a convenience extension method to add itself to the pipeline. We can use that method when configuring the application:

public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles();
app.UseMvc();
}

In addition, since dependency injection is now used throughout the framework, we need to register the services required by MVC on the DI container. I’m not yet familiar with the details of the DI model on ASP.NET 5, but there’s another method (besides Configure) that the framework invokes by convention when starting up an application:

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}

Note the usage of AddMvc, an extension method also included in MVC to register its services on the container.

MVC 6 Includes the features that were previously found on both MVC and Web API. Everything should be familiar, having in mind that the base HTTP programming model is a bit different. That said, adding a controller is straightforward. Just add a class whose name has the Controller suffix, define an action and its route and your good to go. You don’t need to extend the base Controller class, even though it has many useful methods and properties (View(), Redirect(), Request, Response).

public class HelloWorldController
{
[Route("Hello")]
public object Index()
{
return new
{
Message = "Hello ASP.NET 5 world!",
Time = DateTime.Now.ToString(),
};
}
}

If we run the app from the console an navigate to http://localhost:5000/hello we’ll get a JSON response returned by the controller. The same controller can also have an action returning an IActionResult which corresponds to a view:

[Route("Hello/Goodbye")]
public IActionResult Goodbye()
{
return View();
}

And that’s it for now!

Advertisement

Hello ASP.NET 5 World – Part II

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.

Hello ASP.NET 5 World – Part I

First of all, Visual Studio 2015 CTP 6 was released this week and with it the beta 3 of CoreCLR and ASP.NET 5. I’ll be using beta 3 for this post. If you’re not installing VS, make sure you re-install KVM, because there were a few changes (different layout on the file system, new commands on KPM, etc.).

Programming model

In my previous post I wasn’t clear about one thing: ASP.NET’s 5 side-by-side deployment, pay-for-play and multi-host approach also means that the monolithic System.Web is gone. No more IHttpHandler, IHtpModule and co. Of course many of the features on System.Web will have its counterpart on ASP.NET 5 stack.

ASP.NET 5 is OWINish. In fact, the Katana project was integrated into ASP.NET 5, defining the base programming model. This means we’ll deal with middlewares, AppFunc and the enviroment dictionary. Well, actually the ASP.NET 5 HTTP object model has a higher abstraction level rather than exposing the raw OWIN concepts.That’s why I said it is “OWINish”.

Hello World!

So, what does it take to have a simple “Hello World” in ASP.NET 5? It’s actually quite simple. I found this nice tutorial with all the steps to set up from the ground, so I won’t reproduce them here. Just note that the post is based on beta 2 and I’ll be using beta 3.

The bare minimum is to define: a Startup class, where you configure your application. In this case, I’m configuring it to say hello as a response to all the requests.

using System;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;

namespace HelloWorld.Web
{
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Run(ctx => ctx.Response.WriteAsync("Hello ASP.NET 5 world! Time: " + DateTime.Now));
}
}
}

And a project.json file with the application dependencies. In this case I’m also configuring a command to be able to run the application from the command line, since I’ll be using a self-host.

{
"dependencies": {
"Microsoft.AspNet.Hosting": "1.0.0-beta3",
"Microsoft.AspNet.Server.WebListener": "1.0.0-beta3"
},
"commands": {
"web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000"
}
}

The bootstrap is convention-based: ASP.NET searches the main assembly of the application for a class named Startup and then for a method named Configure that has the signature above. The app.Run method is used to register code that kicks in when no other component handles the request. Since I have nothing else, it will run for every request. This is somewhat similar to an IHttpHandler on previous versions.

The web command is an easy way to configure the self-hosted server and then start it using k on the command line. So, if you put the two files above on a folder, you can restore dependencies and run the application from the command line by doing:

kpm restore
k web

You should see a “Started” message on the console and then you can access the application on http://localhost:5000. And that’s it!

On the following post I’ll add a few more bits on this example, namely registering a middleware and hosting on IIS express, as well as looking a bit more into the HTTP abstractions and comparing them to the ones previously found on Katana project.