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.