ASP.NET vNext (MVC6) Ground Up #2 - Plugging in MVC

Edit: This post has been updated to beta2.

Continuing on from Part #1 of the Ground Up Series, we'll be building on the concepts to plug in MVC6.

The source code is available here.

Install MVC6 dependency with:

kpm install Microsoft.AspNet.Mvc 6.0.0-beta2  

Now we can look at wiring it all together.

"Adding" Services, "Using" Middleware

Dependency Injection is now a first-class citizen throughout the entire ASP.NET5 stack. Let's revise our Startup.cs Configure method to the following:

public void Configure(IApplicationBuilder app)  
{
    app.UseServices(services => services.AddMvc());
    app.UseMvc();
}

AddMvc() is an extension method in the Microsoft.Framework.DependencyInjection namespace which you will need to add a using statement for.

The UseXXX and AddXXX naming convention here is very deliberate. You Add services to the Dependency Injection container and you Use components in the Middleware pipeline. In this example, the AddMvc() extension method is Adding all the services that MVC depends on to the Dependency Inection container and UseMvc is registering that you want to Use the MVC components in the Middleware pipeline.

These extension methods are provided purely for convenience as a shorthand for plugging in services/middleware MVC needs. This pattern (of including an extension method to handle wireup) is used frequently with vNext components. We'll look at adding our own as we get further into this series.

Dependency Injection is so imporant that there are now hooks in the framework explicitely designed for wiring services up. Delete the app.UseServices(services => services.AddMvc()); call and add the following method to Startup.cs

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

As mentioned in Part 1, the Framework will automatically look for certain methods to call when it boots your application. ConfigureServices(IServiceCollection services) will automatically be called by the framework before the Configure(IApplicationBuilder app)method.

Ultimately, it does the same thing but is a bit neater (especially once there are a lot of services and middlewares). This isn't just for framework specific parts, you can register your own services here as well.

Our Startup.cs now looks like:

using Microsoft.AspNet.Builder;  
using Microsoft.Framework.DependencyInjection;

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

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

Nice and clean.

Routing

The static route tables from MVC5 are gone however the wireup remains largely familar. Modify the UseMvc() method to use the following overload in the Microsoft.AspNet.Routing namespace:

app.UseMvc(routes =>  
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});

There is one subtle change here in that we're using the inline route contraints to provide the default values for the Controller (Home) and Action (Index). We're also flagging the Id as being optional. This was a feature in Attribute Routing which has now made it's way over to "regular" routing. The old method is still around if you'd prefer it.

Controllers

Controllers too should be immediately familar to users of previous versions of MVC.

public class HomeController  
{
    public string Index()
    {
        return "Hello World";
    }
}

You no longer need to inherit from a base Controller class, it is driven by naming convention alone, anything that has a *Controller suffix will be automatically discovered by the framework. In practice, you will often want to inherit from Controller as it will make your life a bit easier but it's entirely optional.

Restart k web and hit http://localhost:5000 and you'll now see Hello World - this time, being driven by MVC6.

We're skipping the View part entirely here, so we can expand that with:

public class HomeController  
{
    public IActionResult Index()
    {
        return new ViewResult();
    }
}

Which will now return in the conventional location of ~/Views/ControllerName/ActionName.cshtml:, which translates to~/Views/Home/Index.cshtml.

If we needed ViewData information (for instance), we can inject that property into our controller:

[Activate]
public ViewDataDictionary ViewData { get; set; }  

This [Activate] attribute wires into the depedency injection framework and it will automatically be instantiated on your controller. If you need other parts of the framework (or indeed your own services), you can inject them in as well.

And then we can go the whole hog and just derive from Microsoft.AspNet.Mvc.Controller just like we would with MVC5. In doing so, it will take care of all of this for us.

public class HomeController : Controller  
{
    public IActionResult Index()
    {
        return View();
    }
}

The key point I want to get across here is that you can bite off as much of the framework as you want. From simple "POCO" controllers all the way up to inheriting from Controller which will give you all the bells and whistles.

Starting to pick up steam now, in the next post we'll look at wiring up EF7 and exposing a database to our app.

comments powered by Disqus