April 2, 2013

Nancy vs ASP.NET MVC - Getting Started

In this post we look at how to create a very basic web site from scratch using both Nancy and ASP.NET MVC frameworks.

The goal is to set a welcome message on the server and then display this on a HTML page.

You can find the source code that will accompany this series of blog posts on Github.

Getting started with ASP.NET MVC

As ASP.NET MVC has been around for some time the tooling support within Visual Studio is pretty good. As such you can scaffold together a basic application without writing much code.

To kick things off, go to File > New Project.

In the New Project dialog choose the “ASP.NET MVC 4 Web Application” project template:

MVC Project Templates

You’ll then be presented with a number of template options. The “Internet Application” for example is preconfigured with Forms Authentication and includes some default Views, CSS and jQuery.

Since the goal is to build an application from scratch we’ll choose the “Empty” template.

MVC Project Template Options

This is what the new project looks like in Solution Explorer:

MVC Solution Explorer

A convention introduced in the MVC 4 project templates was to add all startup/initialization code under the App_Start directory. The astute among you may have noticed “WebApiConfig.cs” which is strange since we created an ASP.NET MVC project, not Web API.

This is still one of my biggest frustrations with the ASP.NET templates. It seems that even after all this time Microsoft have not quite grasped the concept of “Empty”.

Looking at the NuGet package manager we can see exactly what has been installed in our empty project.

MVC Default NuGet packages

After removing the Web API packages we can see what is actually required to run an ASP.NET MVC 4 web application:

MVC Updated NuGet packages

With that that sorted let’s create a Controller (the “C” in MVC) to handle requests to the site.

Right click on the Controllers directory and choose “Add Controller”. The Add Controller dialog allows you to choose from a number of templates - it can even create a controller based on a Model and Entity Framework Data Context - very handy for CRUD applications.

We’ll stick with the “Empty MVC controller” template which includes an “Index” action returning a ViewResult.

MVC Add Controller Dialog

We’re going to store our welcome message in the ViewBag dynamic dictionary, just one of the ways of passing information from an MVC Controller to a View. Another option (and one that I would otherwise recommend) is to use a strongly typed model. We’ll cover this in a later post.

Our completed controller can be seen below:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        ViewBag.WelcomeMessage = "Welcome to ASP.NET MVC!";
        return View();
    }
}

Since the action returns a ViewResult we need to create a View. As we’ve not specified a name of our view the default conventions are to look for one named Index (the name of our action) in either “~/views/shared” or “~/views/home/”. Fortunately we can use just use the tooling to make this process a bit easier. Right click on the Index method within your controller and select “Add View”.

MVC Add View dialog

The Add View dialog can save a lot of time. Creating strongly typed data entry forms is trivial thanks to its scaffold templates. You can also choose to add a partial view or to make use of a layout (master) page.

In this example, we’ll just leave the defaults as they are and click “Add”.

By default, the MVC template uses the Razor view engine. To display the message we set in the Controller we just use @ViewBag.WelcomeMessage. The updated view page can be seen below:

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>NancyVsMvc.Mvc - Welcome!</title>
</head>
<body>
    <div>
        <h1>@ViewBag.WelcomeMessage</h1>
    </div>
</body>
</html>

Hit F5 and voila:

MVC Complete

You may wonder how ASP.NET MVC knew to invoke our Controller action when we ran the application. This is thanks to the code in App_Start/RouteConfig.cs which sets up a default route to the “Index” action on the “Home” controller. If you wanted to name your controller something different, you would just need to update this route definition:

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

We’ll cover routing in more detail in a later blog post.

Getting started with Nancy

Getting started with Nancy involves a little less ceremony, partly due to the lack of project templates/tooling.

Go to File > New Project and choose the “ASP.NET Empty Web Application” template:

Nancy Project Template

At least this time, we do get an empty project.

Nancy Solution Explorer

We need to install a couple of NuGet packages so we can use Nancy. The first is the core Nancy runtime and the second is the ASP.NET host (since Nancy is not tied to a specific hosting environment). You can install both of these by issuing the following command from the Package Manager Console:

Install-Package Nancy.Hosting.Aspnet

Or using the NuGet GUI (Right Click project > Manage NuGet Packages):

Nancy NuGet

Now we need to create a Module that will handle the request to our Nancy site. You can think of a module a bit like the Controller in ASP.NET MVC although it’s worth noting that Nancy can do much more than MVC.

You can put your module classes anywhere but a common convention is to create them under a “Modules” directory. Create a new class “HomeModule” as below:

using Nancy;

namespace NancyVsMvc.Nancy.Modules
{
    public class HomeModule : NancyModule
    {
        public HomeModule()
        {
            Get["/"] = _ =>
            {
                dynamic viewBag = new DynamicDictionary();
                viewBag.WelcomeMessage = "Welcome to Nancy!";
                return View["home", viewBag];
            };
        }
    }
}

Here we are declaring a delegate function (using a lambda expression) that will handle any requests to the root of our application ("/"). If you’re new to lambdas this syntax may look a little funky but it does make things nice and terse.

Since the default view engine (the Super Simple View Engine) in Nancy does not support ViewBag we’re simulating one using Nancy’s DynamicDictionary class and passing that to our View as a model.

Like ASP.NET MVC, Nancy includes a number of conventions for locating Views, one of these being to look inside a “Views” directory. Create a new HTML page at “/views/home.html” and update as below:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>NancyVsMvc.Mvc - Welcome!</title>
</head>
<body>
    <h1>@Model.WelcomeMessage</h1>
</body>
</html>

You may notice we are just using a standard HTML page. Nancy will automatically process this using the Super Simple View Engine. If you need a richer templating engine you can use Razor instead (installable via a NuGet package). This will be covered in a later blog post.

Hit F5 and see Nancy come to life!

Nancy Complete

Conclusion

One of the most noticeable differences between the two frameworks is the tooling available.

Project templates are great for people new to ASP.NET or for demo purposes but for more experienced developers they can often get in the way.

One issue is that most of the documentation/tutorials for ASP.NET MVC involve using these pre-configured templates in some way. This can sometimes lead to a poor understanding of the framework and what all these different NuGet packages actually do - is it any wonder so many people on StackOverflow refer to ASP.NET Web API as ASP.NET MVC Web API?!

This is something that I really like about Nancy and is akin to frameworks like NodeJS. The core of Nancy is simple and lightweight (yet still very powerful). You add the modules you need, when you need them.

I would however like to see tooling added for creating Views in Nancy and it looks like this may be answered in the next ASP.NET release:

All MVC and Web API tooling will be available to all Web projects. For example, you will be able to scaffold MVC and Web API controllers in any web project, not just MVC or Web API projects.

Another difference is how routes are defined in both frameworks. In ASP.NET MVC route definitions are separate from the Controller Actions that they invoke. In Nancy they are inline (personally I prefer this). I’ll cover this more in a later post as well as Attribute Routing which makes it possible to perform inline routing in ASP.NET MVC.

Beyond that I hope you can see that it is pretty simple to get started with both frameworks. So what are you waiting for?!

© 2022 Ben Foster