Implementing a Blog Site Using ASP.NET MVC

To illustrate how to write Razor views in an ASP.NET MVC application, let’s revisit the WebMatrix blog website and rewrite it “the MVC way.” To start out, open up Visual Studio and choose File → New Project..., and then select the ASP.NET MVC 3 Web Application option. Name the new project MvcRazorBlog, as shown in Figure 4-1.

Creating a new MVC application

Figure 4-1. Creating a new MVC application

Then, from the New ASP.NET MVC 3 Project Wizard, select the Empty site template and the Razor View Engine (these should be the default settings); Figure 4-2 provides an example.

The ASP.NET MVC 3 Project Wizard

Figure 4-2. The ASP.NET MVC 3 Project Wizard

Once completed, your project should resemble the directory structure shown in Figure 4-3.

Folder structure for a new ASP.NET MVC project

Figure 4-3. Folder structure for a new ASP.NET MVC project

The Model

The blog site example from the WebMatrix chapter didn’t involve an official “model.” That is, you never created any classes to hold and manage data; all of the data interaction used method calls directly to the database and saved the results in local dynamic variables. WebMatrix can get away with accessing and using the data directly because of the page-based architecture it is built on; every page is responsible for its own data access (with assistance from helper objects) and for manipulating that data.

ASP.NET MVC’s architecture dictates that the Model and the View are two separate entities, so in order to demonstrate the Razor syntax within ASP.NET MVC’s Razor View Engine, you should create a model that can hold and manage the site’s data. Since you’ve already implemented the blog site once, you already know what data the site uses. To create the Model for the ASP.NET MVC blog site, add a new class named Post to the website’s Models folder, with the following code:

namespace MvcRazorBlog.Models
{
    public class Post
    {
        public long ID { get; set; }
        public string Title { get; set; }
        public string Body { get; set; }
    }
}

Since the blog site doesn’t require very complex data, the Post class is all that’s needed at this point. Once it’s in place, you can create the Controller that will populate the Post class with data from the database and pass it to the View.

The Controller

The default Empty site template chosen earlier expects a controller named HomeController, which ASP.NET MVC adds to the Controllers folder by convention. To create an empty controller, right-click on the Controllers folder and select Add → Controller…, entering the name HomeController.

The wizard will ask you if you’d like it to generate Create, Update, Delete, and Details actions for you. We won’t use those actions in this book, but feel free to let the wizard generate them for you if you’re interested to see what they look like. The wizard will create a new class file with one action named Index:

using System.Web.Mvc;

namespace MvcRazorBlog.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }
}

According to ASP.NET MVC’s default routes, the HomeController’s Index action handles requests for the site’s home page (the root of the site without specifying any file or folder names). The behavior we want to implement in the Index action directly correlates to logic used in the sample WebMatrix site’s Default.cshtml page in Chapter 2. So, the next step is to reproduce the same data access logic that the Default.cshtml page uses to retrieve Post data.

Data access with Entity Framework code first

For better or worse, ASP.NET MVC does not offer the same Database object included in the WebMatrix platform. Instead, Microsoft’s Entity Framework 4.1 (and up) and its Code First functionality make data access just as easy as it is in WebMatrix, or perhaps more so.

To get started with Entity Framework Code First, you’ll need to install it using the NuGet Package Manager, a Visual Studio extension installed as part of the ASP.NET MVC 3 install process.

After it’s installed, the only other step you need to take in order to use the Entity Framework Code First framework is to create a custom class that derives from the System.Data.Entity.DbContext class, which tells Entity Framework which objects you’d like to persist and retrieve from the database. A working DbContext implementation can be as simple as the following:

using System.Data.Entity;
using MvcRazorBlog.Models;

public class BlogContext : DbContext
{
    public DbSet<Post> Posts;
}

This code extends the DbContext class, exposing a single property (Posts) of type DBSet<Post>. It is the DbSet<Post> portion of this property that indicates to Entity Framework that you’d like to use the Post class as your model for data access and that these objects can be found in the Posts table (corresponding to the name of the property) in the database.

That’s all that’s needed in regards to setup and configuration; Entity Framework relies on “convention over configuration” to determine the rest. Entity Framework will even create the database for you if it does not exist when you attempt to access it!

Querying an Entity Framework Code First data context is even easier than writing one. All you need to do is create an instance of a DbContext and start making standard LINQ calls against the DbSet<TModel> properties defined on the context.

Thus, retrieving all of the Posts from the Blog database from the HomeController’s Index action is trivial:

public class HomeController {
    public ActionResult Index()
    {
        var posts = new BlogContext().Posts;
        return View("Index");
    }
}

Once the Index action retrieves the blog post data from the database, it needs to select the appropriate View and pass the post data to that View. Since the MVC pattern deliberately decouples views and controllers, the controller cannot directly communicate with the selected view to provide the view with the data it needs. In order to get around this limitation, ASP.NET MVC relies on an intermediary dictionary via a property named ViewData. Controllers and views both contain this property, so it is easily accessible in both layers. Here is the updated Index action, adding a line of code to assign the blog post data to the ViewData dictionary for use in the views that you will create in the coming sections:

public class HomeController {
    public ActionResult Index()
    {
        var posts = new BlogContext().Posts;

        ViewData["Posts"] = posts;

        return View("Index");
    }
}

Though passing values to views through the ViewData dictionary works just fine, “magic values” (string constants referenced in multiple places) like "Posts" can become difficult to manage and maintain. Additionally, the ViewData dictionary is not strongly-typed, so Visual Studio cannot provide you with IntelliSense on any values passed into it. Instead of the ViewData dictionary, the preferred approach for passing data from controllers to views is through the model parameter of the View() helper method.

Below you can see the Index action updated to pass the Posts data via the View() helper method:

Index action retrieving blog posts and passing them to the view
public ActionResult Index()
{
    var posts = new BlogContext().Posts;
    return View("Index", posts);
}

At this point—even though you have not yet created the View required to render HTML to the user—you should be able to verify that this code works by placing a debug breakpoint on the final return View("Index"); line and hitting F5 to run the website. If everything works, execution should stop at the breakpoint and the posts variable should contain a list of Post objects with the data from your database!

Convention versus Configuration

To make website development easier and help developers be more productive, ASP.NET MVC relies on the concept of “convention over configuration” whenever possible. What this means is that, instead of relying on explicit configuration settings, ASP.NET MVC simply assumes that developers will follow certain conventions as they create website components.

The previous section applied several conventions when creating the HomeController and its Index action. The first convention was placing the controller in the project’s Controllers folder. Though not required for the application to compile and function, keeping your controllers in the Controllers folder is a standard practice. The second convention was the name of the controller, HomeController. Since it is a very good practice to give classes descriptive names, standard conventions recommend applying the “Controller” suffix to controller class names. When referring to the controller throughout the application, however, it is much more straightforward to simply refer to “Home” instead of the full name, “HomeController.”

The ASP.NET MVC framework addresses this conflict during the application’s startup phase, when it searches through all of the website’s assemblies, registering classes that extend ASP.NET MVC’s ControllerBase base class (using the base class as yet another convention). As the framework locates classes that derive from ControllerBase, it adds them to its internal dictionary using the class’s name—after removing the “Controller” suffix—as the dictionary key. Thus, even though the controller is named “HomeController,” the rest of the application can simply refer to it as “Home.”

At first glance, the concept of convention over configuration may seem trivial. However, when taken altogether over the course of a large site, many of these seemingly small or meaningless optimizations can really add up to significant time savings, improved code readability, and increased developer productivity.

Get Programming Razor now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.