Category Archives: MVC

JSON with ASP.NET MVC 4

As a newcomer to JavaScript and jQuery, I wanted to write a (supposedly) simple little web site which used JSON (JavaScript Object Notation) to transmit information from a database to a web page. Surprisingly there didn’t seem to be any self-contained example or tutorial (that I could find) that showed how to do this basic operation. So here is the result of my attempt. It turns out that it is actually quite simple, once you know what to do.

First off, what is JSON? It is an alternative to XML as a way of sending information from one device to another. It’s a subset of the notation that can be used in JavaScript to define an object literal, which we saw in the last post. As an example, we might have some information on the numbers of various titles of comic books that are stored in a database. After we’ve retrieved this data from the database, we can encode it into JSON, so that it looks like this:

[
  {"Title":"Batman","Count":1},
  {"Title":"Fantastic Four","Count":2},
  {"Title":"Spider-man","Count":2},
  {"Title":"Superman","Count":1},
  {"Title":"Thor","Count":2}
]

That is, the data are stored as name-value pairs. In this case, each element in the array is actually a compound object consisting of two name-value pairs (Title and Count). We could have a simple list of single name-value pairs, or we could have deeper nesting of objects. There are various restrictions on the syntax for JSON objects, but as we’ll see, in MVC 4 you won’t usually have to write your own JSON, since there is a library routine that does it for you.

Now that we know what JSON is, how do we use it as a mediator between a database and a web page in ASP.NET MVC 4? We’ve seen that the procedure for generating web pages in MVC is as follows.

  1. Write a controller that contains a method that is called when a client requests a web page from the server.
  2. Write a view that is linked to the controller method, and which generates the markup that is returned to the client.

The controller method will usually collect some data from some other source, such as a database or some other C# code (which is usually part of the Model in MVC). This data is then packaged up, possibly in a C# object, and sent to the View, where the View formats the data and generates the HTML which is interpreted by the browser.

The procedure for using JSON doesn’t quite fit this pattern. Basically what happens is this:

  1. Client requests a web page.
  2. Controller method is called to process this request.
  3. The corresponding View is returned to the browser.
  4. The View contains some JavaScript code that makes another request to the server, this time asking for some data in JSON format.
  5. different Controller method from that called in step 2 is called to generate the JSON, which is returned to the browser.
  6. The JavaScript code processes the JSON and generates some HTML which is displayed.

The key point is that the JSON is not meant to be displayed as raw data by the browser; rather, it is retrieved by the browser and then processed on the client side before it is displayed.

We’ll illustrate this by showing how the data above can be obtained from the database and sent to a web page using JSON. First, we’ll add a controller to our ComicShop project that we’ve been using to demostrate things:

using System.Web.Mvc;
using ComicShop.Models;
using System.Collections.Generic;

namespace ComicShop.Controllers
{
  public class JsonController : Controller
  {
    //
    // GET: /Json/

    public ActionResult Index()
    {
      return View();
    }

    private IComicRepository comicRepository;

    public JsonController()
    {
      comicRepository = new ComicRepository();
    }

    public JsonController(IComicRepository comicRepository)
    {
      this.comicRepository = comicRepository;
    }

    public ViewResult JsonSummary()
    {
      return View();
    }

    public ActionResult Summary()
    {
      IEnumerable<ComicSummary> summaries = comicRepository.GetSummaries();
      return Json(summaries, JsonRequestBehavior.AllowGet);
    }

  }
}

This controller uses the IComicRepository interface and ComicRepository class that we introduced earlier. This controller contains two methods of interest here. The one called JsonSummary() simply returns a View, which is the View that requests the JSON data (we’ll get to this View in a moment).

The Summary() method is the one that produces the JSON data. The first line in this method requests the data from the database (see the earlier post for details of how this is done; all that’s important here is that we do get this data). The data is returned as an IEnumerable<ComicSummary> list. The ComicSummary class is defined as:

namespace ComicShop.Models
{
  public class ComicSummary
  {
    public string Title { get; set; }
    public int Count { get; set; }
  }
}

That is, it contains two data fields named Title and Count.

The second line in Summary() calls the library method Json() to create the JSON data. It is passed the list of ComicSummary objects in the variable summaries. The second parameter allows Summary() to provide JSON data in response to an HTTP Get request (by default, such a response is blocked for security reasons, so this parameter is needed). This returns the JSON string we gave above.

That’s all there is to producing JSON data (as promised, you didn’t have to actually write any raw JSON yourself, since the Json() method does it for you). If you want to verify that Summary() actually works, you can call it directly from a web browser by using the URL http://localhost:36195/Json/Summary (the port number for your localhost server will probably be different; what’s important is the path /Json/Summary), and you should see the raw JSON data printed in the browser.

Note that we did not associate a View with the Summary() controller method. As far as the browser is concerned, it is receiving raw text as a response to its request to Summary, so it just displays that. We need to do something special if we want it to interpret the JSON as data and incorporate it into a ‘real’ web page.

To that end, we turn our attention to the JsonSummary() controller method, and have a look at its View. This is in the file JsonSummary.cshtml:

<h2>JsonSummary</h2>
<script>
    $.getJSON('/Json/Summary',  function (data) {
        var items = [];
        $.each(data, function (key, val) {
            items.push('<li>' + key + ': ' + val.Title + ' (' + val.Count + ')</li>');
        });

        $('<ul/>', {
            html: items.join('')
        }).appendTo('body');
    });
</script>

As you can see, most of this file is JavaScript. However, it’s not all primitive JavaScript; it makes use of jQuery, so you need to make sure your web project has jQuery installed. If you started with an Empty project, you’ll need to do this yourself; if you started with a full Internet project, it will already be included.

To add in jQuery, right-click on the Solution in SolutionExplorer and select Manage NuGet Packages. Search in the Online section and find jQuery, then click Install. JSON should already be installed – you can check this by opening up References in SolutionExplorer and seeing that Newtonsoft.Json  is included in the list.

NuGet should take care of installing these packages and should find some jQuery JavaScript files in your Scripts folder (if you didn’t have a Scripts folder, it will be created by the installation).

We’re not quite done yet, though. In order for jQuery to be used in your View, that View needs to run the jQuery script. You could include a <script> tag in the View file itself, but if you plan on using jQuery in a lot of Views, it makes more sense to put it in the common layout file which we considered earlier. This file is called _Layout.cshtml and is in the Shared folder within the Views folder. Add the call to the jquery script in the <head> section of the layout. The modified _Layout.cshtml file looks like this:

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <script src="~/Scripts/jquery-1.8.2.js"></script>
    <meta name="viewport" content="width=device-width" />
    <title>Comics</title>
</head>
<body>
    <h2>Comic Shop</h2>
    <div>
        @RenderBody()
    </div>
</body>
</html>

The call to the script is on line 9. The actual version number of jquery may differ from 1.8.2 if you install it later on, but just insert whatever version you got from NuGet.

That’s all we need to get the JavaScript to run, but there’s one more thing that’s very useful, and that’s to get Intellisense working for jQuery. Complete instructions for doing this are here, provided you’re using VS 2012. My _references.js file looks like this:

/// <reference path="jquery-1.8.2.intellisense.js" />
/// <reference path="jquery-1.8.2.js" />

Right, now we can look (finally) at JsonSummary.cshtml. A lot of the code there relies on a knowledge of JavaScript and jQuery syntax, so I won’t go through it in detail. However, I’ll mention a few key points so you can adapt it for your own purposes.

First, the $.getJSON() call is a jQuery method which makes a request to the URL given as its first argument for some JSON data. In our case, we use a relative URL /Json/Summary (the leading / is important: don’t leave it out!). If this call is successful, the JavaScript function given as the second argument to $.getJSON is called. (If the call fails, this function isn’t called, and you’ll get nothing on your web page apart from the HTML that is outside the <script> tag. This can make debugging a nightmare, since you won’t know what’s wrong, but never mind.)

The argument ‘data’ sent to this function is the JSON code. This function then constructs an array called ‘items’ by iterating through ‘data’ using the jQuery $.each() method. The second argument to $.each() is another function, this time taking two arguments. The ‘key’ argument is the integer index of the element from ‘data’ that is being processed, and ‘val’ is that actual element from ‘data’. Remember from the JSON above that each element in ‘data’ is a compound object of type ComicSummary, so it contains a Title and a Count field. We access these fields to create a HTML list entry on line 6, and push this onto the items array.

The last bit of code on lines 9 to 11 creates a <ul> tag and adds the items list to it, then it adds the <ul> tag to the body of the page. The final result looks like this:

Advertisements

MVC: user input model

In the last post, we saw how restructuring the code so that a view model is used to prepare the data for the view helps decouple the view from the calculations required to process the data before displaying it. In this post, we’ll have a look at how to apply a similar approach to user input.

We’ll modify the ComicShop site by adding in a boolean parameter specifying whether we’ve read a particular comic. To do this, we’ll need to modify the underlying database by adding a Read field. You can do this by opening the database in Visual Studio’s Server Explorer (double-click on the database file in Solution Explorer to do this), then navigating to the Books table, then right-clicking and selecting Edit Table Schema. Add in a column called Read, and set its type to ‘bit’. Set its default value to 0.

We also need to modify the Book class by adding a bool property called Read.

To make things easier in what follows, we will also modify the home page so that it displays the Read status of each comic book. We can do this by modifying the IndexModel.cshtml code to this:

@using ComicShop.Models;
@model List<Book>

<h2>Comics</h2>
<p><a href="/Home/Add">Add new comic</a></p>
<p><a href="/Home/Summary">Summary</a></p>
<p><a href="/Home/Read">Comics read</a></p>

<ul>
    @foreach (var comic in @Model)
    {
        <li>
                @comic.Title: <b>@comic.Volume</b> (@comic.Issue) [@(comic.Read ? "Read" : "Unread")]
        </li>
    }
</ul>

Now we’re ready to add a page on which the user can change the Read status of one or more comics. We’d like to display a table of the comics in the database, with each row in the table showing the title, volume and issue of the comic, and a checkbox allowing the Read status to be edited. The controller method for this is very simple:

    public ViewResult Read()
    {
      var model = comicRepository.GetComicList();
      return View(model);
    }

Before we construct the view, we need to stop and think about what the Read view will return. All we really need to identify the read status of a comic is the comic’s primary key (the Id column in the database) and the read status itself. The input model for this page is then the simple class:

namespace ComicShop.Models
{
  public class ComicReadStatus
  {
    public int Id { get; set; }
    public bool Read { get; set; }
  }
}

This just uses the same code we had before, since the view requires the same data as the home page. The Read.cshtml file looks like this:

@using ComicShop.Models;
@model IEnumerable<Book>

@{
    ViewBag.Title = "Read";
}

<h2>Comics Read</h2>
<div>
    <form action="@Url.Action("UpdateReadStatus")" method="post">
        <table>
            <tr>
                <th>Title</th>
                <th>Volume</th>
                <th>Issue</th>
                <th>Read?</th>
            </tr>
            @{ int index = 0; }
            @foreach (var comic in Model)
            {
                <tr>
                    <td>@comic.Title</td>
                    <td>@comic.Volume</td>
                    <td>@comic.Issue</td>
                    <td>
                        @Html.CheckBox("comicRead[" + index + "].Read", comic.Read)
                        <input name="@("comicRead[" + index + "].Id")" value="@comic.Id" type="hidden" />
                    </td>
                </tr>
                index++;
            }
        </table>
        <button name="submit">Update</button>
    </form>
</div>

The page constructs a table in the same way as we did for the ComicSummary page in the last post. The one notable feature here is the addition of the checkbox. Rather than use bare HTML for this, we’ve used one of MVC’s Html helper functions. This function takes 2 parameters; the first is the name of the checkbox and the second is its initial value.

Since we’re displaying a table of comics, there will be a checkbox for each comic, so we name the checkbox in such a way that the table builds an array. The name of the checkbox is translated dynamically into a data type, so we build up the array by defining an ‘index’ parameter to number the rows in the table and insert this into the ‘comicRead’ array for each row in the table. It’s important here to make sure that the properties of the array are the same as those in the data type we are to export from the form. In this case, we’ll be exporting a list of ComicReadStatus objects, so each array element must have a bool Read and an int Id property. The Read property will be set to the value in the checkbox when the form’s submit button is pressed.

If you’re familiar with basic HTML, you might know that a form returns a value for the checkbox only if it is checked, so that if the checkbox is cleared, there would be no corresponding data sent in the post from the form. The Html.Checkbox() function gets around this problem by defining an additional hidden HTML control with the same name as the checkbox, and a permanent value of ‘false’. If the checkbox is true, it overrides this hidden field, but if the checkbox is false it is ignored and the hidden field then gets sent back from the form. Thus we will have a definite value for each checkbox whether it is true or false.

The explicit hidden field in the Read.cshtml code passes the comic’s Id value back from the form. Thus the output of the form is a list of ComicReadStatus objects, each of which contains a primary key of a comic and its Read value as specified by the user on the form.

In the form definition on line 10, we see that the action called by submitting the form is UpdateReadStatus, so we’ll need to write that before we try to use the form (although you can run the site now and go to the /Home/Read page to see the form if you like).

The action method in HomeController is again very simple:

    public ActionResult UpdateReadStatus(List<ComicReadStatus> comicRead)
    {
      comicRepository.UpdateReadStatus(comicRead);
      return RedirectToAction("Index");
    }

The input parameter is a List<ComicReadStatus>. You might wonder how the program knows to convert the data sent back from the form into this structure. This is a feature of MVC’s model binding technology, and for now it’s probably safer just to accept that it works. One thing is important though: you must ensure that the name of the parameter (‘comicRead’ here) is the same as that of the array you defined in Read.cshtml’s checkbox. Unlike the usual C# parameter names, where the parameter in the function definition doesn’t have to match that of the variable that is sent into the function, here it does matter, and if you make the names different, the object received by the action method is null (with all the pain that that generates when you try to run the method).

We’ve delegated the work done by UpdateReadStatus() to a method called UpdateReadStatus() in the ComicRepository. This allows us to decouple the controller from the access to the data source, as we’ve done so far in order to enable unit testing. The last line of the action method redirects the browser back to the home page where you can see the results of your edits.

In the ComicRepository class that we’ve been using for interaction with the database, we therefore need to write some code which saves any changes made by the user back to the database. Herein lies a bit of a problem, since the Read view has no connection with, or knowledge of, where its data comes from (which is correct). However, as such, there’s no way to tell from the data sent back by the form which comics have had their Read status changed. There’s really only one way we can be sure of saving all the changes to the database: we’ll have to iterate over all the comics that were listed on the Read view and check to see which ones have had their Read status changed. This obviously isn’t very efficient, but the only other way of doing this involves responding directly to the user’s clicks on the Read page, and that will take us too far afield. So we’ll content ourselves with a fairly brute force method for updating the database. (Actually, a proper view wouldn’t have that many lines in a table anyway, so this probably isn’t all that inefficient, but still…)

Here’s the code in the ComicRepository class:

    public void UpdateReadStatus(List<ComicReadStatus> comicReadStatus)
    {
      foreach (var comic in comicReadStatus)
      {
        Book book = database.ComicBooks.Find(comic.Id);
        if (book.Read != comic.Read)
        {
          book.Read = comic.Read;
          database.Entry(book).State = System.Data.EntityState.Modified;
        }
        database.SaveChanges();
      }
    }

For each comic in the list, we use the DbSet’s Find() method to look up the full comic object in the database. Remember that the comicReadStatus list contains only ComicReadStatus objects, which contain only the Id and Read fields for a given comic book. The Find() method uses an object’s primary key to look it up in the database and then returns the full object.

We then check to see if the Read field has changed and if so, we change the Read field in the full Book object, and then mark this object’s State as Modified. Finally SaveChanges() will save all the rows that have been marked as modified.

MVC: the view model

The ComicShop application we’ve presented so far has been quite basic, in that it does nothing more than allow the user to store comics in a local database, and display a list of these comics on the home page. In the process of creating the application, though, we’ve shown the division of labour between the model (where the data are stored and manipulated), the controller (which handles requests from the user and decides which view to display), and the view (which creates the actual HTML that is sent back to the browser).

You might think that, having covered all three components for which MVC is named, we’re finished with the basics. However, there is another logical component that forms part of the design when the application becomes anything more than very simple. This is the view model. (The view model occupies a more central position in another design system known as MVVM (thanks Stuart!), but we’ll leave a discussion of that until later.)

To illustrate the need for a view model (and to explain what it is), suppose we wanted to add a web page that displayed a summary of the comics in the database by listing each unique title followed by the number of comics of that title in the database. Ultimately, we’d like to display this information as a table in HTML, where each row in the table consists of a string (the title) and an int (the count for that title). To obtain this information, we need to query the database and do a count of each title returned. Where should this work be done?

One option is that the controller queries the database for a complete list of comics (as it does for the page that displays the complete list), and sends this list as is to the view, leaving the view to count up the number of comics for each title and then display the results. This isn’t very efficient, since the view is being forced to do a lot of stuff that has nothing to do with the display of the page.

Another option is that the controller does the calculations itself and then packages up the results and sends them to the view for display. That seems a little better, since at least the view is being cluttered with calculations. However, it isn’t really the job of the controller either, since its job is mainly to route the page request from the user to the correct view.

The solution currently accepted as best practice is to have the controller create a view model which is then sent to the view. The view model is a mirror in C# code of the data that the view requires in order to produce the HTML. In the case of our ComicShop summary page, we’d like a list of rows for the table, where each row contains the title and count for a group of comics. We therefore create a class representing a single row in the table, which looks like this:

namespace ComicShop.Models
{
  public class ComicSummary
  {
    public string Title { get; set; }
    public int Count { get; set; }
  }
}

The idea is now to have the controller construct the view model as an IEnumerable<ComicSummary> list (that is, a collection of ComicSummary objects that implements the IEnumerable interface), and that is what gets sent to the view. This list is the view model for the view that displays the summary information. It contains only the information that the view needs, and doesn’t require the view to do any further calculation.

Where should this list be constructed? To keep the controller clean, the construction shouldn’t be done directly inside the controller. Farming the process out to a separate class also fits in with the design we adopted when implementing unit testing, since we’d like to be able to test the summary-generation code in the controller without directly accessing the database. A sensible place to put the list-building code, then, is in the classes (one for testing and one for running normally) that implement the IComicRepository interface that we designed in the post on unit testing.

When we’re extracting the information from the database, we can actually do all the calculations required using LINQ. Here’s the method in the ComicRepository class:

    public ComicContext database = new ComicContext("ComicContextDb");
    public IEnumerable<ComicSummary> GetSummaries()
    {
      var summaries = database.ComicBooks.Select(book => book).OrderBy(book => book.Title).
        GroupBy(comic => comic.Title,
        (title, titleGroup) => new ComicSummary
        {
          Title = title,
          Count = titleGroup.Count()
        }
        );
      return  summaries;
    }

The first line in the method is the LINQ code that selects all the comics, orders them by title, and then applies the GroupBy() method to sort them into groups where the key to each group is the Title field. The second argument to GroupBy() is a function which takes two parameters: the first is the title of the comic, and the second (titleGroup) is the group of comics with that title. We then construct a ComicSummary object containing the title and the count of comics in that group. The final returned object is the required IEnumerable<ComicSummary> list.

Back in the HomeController class, we add an action for the Summary page:

    public ViewResult Summary()
    {
      IEnumerable<ComicSummary> summaries = comicRepository.GetSummaries();
      return View(summaries);
    }

(The comicRepository object is initialized in the constructor as before.) The controller code is still very clean, since the work of building the view model is done in ComicRepository.

Finally, the view for the Summary page is also very simple:

@using ComicShop.Models
@model IEnumerable<ComicSummary>

<div>
    <h2>Comic summary</h2>
    <table>
        <tr>
            <th>Title</th>
            <th>Count</th>
        </tr>
        @foreach (var summary in Model)
        {
            <tr>
                <td>@summary.Title</td>
                <td>@summary.Count</td>
            </tr>
        }
    </table>
</div>

The model directive at the top is set to an IEnumerable<ComicSummary> data type, making this a strongly typed view. The rest of the view builds the table by iterating over the elements in the model.

Finally, we can add a GetSummaries() method to our test repository class ComicRepositoryTest. It might look something like this:

    public IEnumerable<ComicSummary> GetSummaries()
    {
      return new[]
      {
        new ComicSummary
        {
          Title = "Superman",
          Count = 3
        },
        new ComicSummary
        {
          Title = "Thor",
          Count = 12
        }
      };
    }

We manually add a couple of ComicSummary objects to a list and return it. To use this, we can add some tests to HomeControllerTests. For example, we can test that the number of entries in the table is 2:

    [TestMethod]
    public void Summary_Count()
    {
      HomeController homeController = new HomeController(
        new ComicRepositoryTest());
      var summary = homeController.Summary();
      var table = summary.Model as ICollection<ComicSummary>;
      Assert.IsTrue(table.Count == 2, "Count is {0}", table.Count);
    }

Since IEnumerable <T> doesn’t support a Count property, we’ve cast the Model field of ‘summary’ to an ICollection, which does have a Count. ICollection inherits IEnumerable, so the cast is valid providing the underlying object implements ICollection, which in this case it does.

Unit testing: decoupling the database

In the last post, we saw how to add a simple unit test to an MVC4 project. At the time, we noted that our ComicShop project wasn’t in the best form for unit testing, since the HomeController accessed the database (in which the comic books are stored) directly. This means that any test of HomeController required interacting with the database, so we’re not testing just the code in the controller in isolation.

Here, we’ll see how to decouple the database from the controller, and in the process, how to add in a localized test for the controller that is independent of the database.

The idea is to define a C# interface whose job it is to provide the connection to the data source. In the functioning application, this interface is implemented by a class that does connect to the database, but for testing purposes, we use another class that also implements this interface, but which provides a test set of data without referring to a database.

To design this interface, we look at the HomeController code, and note that there are, at the moment, only two methods that interact with the database: Index(), which retrieves the list of Books in the database, and the HttpPost version of Add(), which takes data off a form submitted by the user and adds this to the database. The other Add() method just displays a form in which the user enters data; no connection to the database is used here.

Our interface, then, should contain two methods which, in classes implementing the interface, are used to connect to the database in one case and to some local data source in the testing case. Here’s the definition of the interface:

using System.Collections.Generic;

namespace ComicShop.Models
{
  public interface IComicRepository
  {
    List<Book> GetComicList();
    void AddComic(Book book);
  }
}

We’ve added this interface to the Models namespace, since it deals with data storage, and classes that implement it are model classes.

We can now define a class called ComicRepository which implements IComicRepository and move the code relying on the database from HomeController to ComicRepository. This class is as follows:

using System.Collections.Generic;
using System.Linq;

namespace ComicShop.Models
{
  public class ComicRepository : IComicRepository
  {
    public ComicContext database = new ComicContext("ComicContextDb");
    public List<Book> GetComicList()
    {
      var comics = database.ComicBooks.Select(book => book).OrderBy(book => book.Title);
      return comics.ToList();
    }

    public void AddComic(Book book)
    {
      database.ComicBooks.Add(book);
      database.SaveChanges();
    }
  }
}

GetComicList() contacts the database and retrieves the list of books using the same LINQ code as we had in HomeController before. However, it converts the result to a List<Book> and returns it. There is no mention of a View, since that’s the job of the controller; this class should concern itself purely with manipulating the data.

In a similar vein, AddComic() accepts a Book and adds it to the database.

The new version of HomeController now looks like this:

using System.Web.Mvc;
using ComicShop.Models;

namespace ComicShop.Controllers
{
  public class HomeController : Controller
  {
    private IComicRepository comicRepository;

    public HomeController()
    {
      comicRepository = new ComicRepository();
    }

    public HomeController(IComicRepository comicRepository)
    {
      this.comicRepository = comicRepository;
    }

    public ViewResult Index()
    {
      var model = comicRepository.GetComicList();
      return View("IndexModel", model);
    }

    public ActionResult Add()
    {
      return View();
    }

    [HttpPost]
    public ActionResult Add(Book book)
    {
      comicRepository.AddComic(book);
      return Content("New comic added.");
    }
  }
}

All explicit references to the database have been eliminated. The interaction with the data source is done entirely through the comicRepository object.

A couple of important additions have been made: we now have two constructors in HomeController.

The argumentless constructor initializes the comicRepository object to ComicRepository, the class that accesses the database. We want this to be the default behaviour of the controller, since this is what is done when we are running the web site.

The second constructor allows us to specify the repository used by HomeController. We’ll use this constructor when we write the test class.

First, we need to define a test class that implements IComicRepository. This class should use a local data source without any reference to the database. Since the web site uses a List<Book> as its working data structure, we can use this as the test data source. We therefore define ComicRepositoryTest like this:

using System.Collections.Generic;
using ComicShop.Models;

namespace ComicShop.UnitTests.Models
{
  public class ComicRepositoryTest : IComicRepository
  {
    private List<Book> comicRepository;

    public ComicRepositoryTest()
    {
      comicRepository = new List<Book> {
        new Book {
          Title = "Incredible Hulk", Volume = 3, Issue = 134
        },
        new Book {
          Title = "Superboy", Volume = 1, Issue = 17
        }
      };
    }

    public List<Book> GetComicList()
    {
      return comicRepository;
    }

    public void AddComic(Book book)
    {
      comicRepository.Add(book);
    }
  }
}

We’ve put this class in the namespace ComicShop.UnitTests.Models (you’ll need to create a new folder in your tests project in Visual Studio), since it’s a data class. Since it implements IComicRepository, we need a ‘using ComicShop.Models’ at the top.

This class has a constuctor that initializes the List<Book> and adds a couple of Books to it. Note that although this class is in the UnitTests namespace, it’s not a TestClass itself; it’s just an auxiliary class that is used in the testing.

We then implement the two methods in IComicRepository. GetComicList() just returns the List<Book>, and AddComic() adds the Book to the List<Book>.

We can now go back to HomeControllerTests (that we started in the last post), and rewrite the tests properly. The class now looks like this:

using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ComicShop.Controllers;
using ComicShop.Models;
using ComicShop.UnitTests.Models;
using System.Web.Mvc;

namespace ComicShop.UnitTests.Controllers
{
  [TestClass]
  public class HomeControllerTests
  {
    [TestMethod]
    public void Index_ValidView()
    {
      HomeController homeController = new HomeController(
        new ComicRepositoryTest());
      var result = homeController.Index();
      Assert.IsNotNull(result);
    }

    [TestMethod]
    public void Add_AddBook()
    {
      HomeController homeController = new HomeController(
        new ComicRepositoryTest());
      homeController.Add(
        new Book
        {
          Title = "Iron Man",
          Volume = 3,
          Issue = 57,
          Publisher = "Marvel"
        }
      );
      var result = (ViewResult)homeController.Index();
      var modelList = (List<Book>)result.Model;
      Assert.IsTrue(modelList.Count == 3, "Count is {0}", modelList.Count);
    }
  }
}

Each test should be entirely self-contained, so we don’t define any class variables; we create an instance of HomeController within each TestMethod. For the tests, we pass an instance of ComicRepositoryTest to the HomeController constructor, so HomeController uses the local data source rather than the database. The Index_ValidView() test is the same test we wrote in the previous post, except this time there is no interaction with the database.

We’ve added another TestMethod to test adding a Book to the data source. Add_AddBook() calls HomeController’s Add() method with a Book that is created on the spot, rather than using data sent in by the user from a web page. We then retrieve the list of Books by calling Index() and extracting the Model field from the ViewResult. Since the list defined in ComicRepositoryTest had two Books in it and we’ve added another one, the size of the list should now be 3, so that’s what we test in the Assert.IsTrue() statement.

Some of Assert’s methods allow an optional message to be printed out if the test fails. In this case, the last two parameters sent to Assert.IsTrue() are a string and its parameter. If the Count of items in the list is not 3, we’d like to see how many items are in the list, so we print that out. You can test this feature by changing the test so it fails (by testing if Count is 4, say). To see this message, click on the failed test in Visual Studio’s Test Explorer, and the results should show up at the bottom of the panel.

We could go on and add more tests to the ComicShop project, but you should get the idea at this stage.

MVC: unit tests

Having spent all my working life in academia, I never got into the formal-testing-of-code mindset, even though I wrote some fairly hefty programs. Of course I tested my programs, but it was mainly a case of trying every possible scenario by hand and then fixing things that didn’t work.

Testing has turned into something of an industry in its own right. The more extreme testers advocate test-driven development, in which the test for a section of code is written before the code itself, and the code is then written so it passes the test.

Whatever your philosophy on testing, having a set of tests which can be run at any time at the press of a button is surely a nice idea, and Visual Studio has tools that support this form of testing. We’ll have an introductory look at how to include unit tests in an MVC4 project, using Visual Studio 2012 (version 11).

When you create an MVC4 project in VS, there is an option to create a test suite at the same time. However, if you don’t do this and opt instead for the empty project (as we’ve done up to now), it’s easy enough to add in a test project later.

One thing is worth pointing out here, though. Older versions of VS had a feature where you could right-click on a class or method in your code and add a unit test on the fly. For technical reasons, this feature has been removed in VS2012, so the only way of adding tests (as far as I can tell) is via the test project itself.

To add a test project to an existing solution, right-click on the existing solution in Solution Explorer and select Add–>New project, then click on the Visual C#–>Test node and select Unit Test Project. You’ll get a starter C# file which looks like this:

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace ComicShop.UnitTest
{
  [TestClass]
  public class UnitTest1
  {
    [TestMethod]
    public void TestMethod1()
    {
    }
  }
}

Note that a class used for unit testing must have the attribute TestClass, and a method must have the attribute TestMethod.

Even at this stage, we can run the test. In the Test menu, select Windows–>Test explorer, and in the Test Explorer window, click on Run All. Since there are no conditions yet that can fail, the test should pass, and you’ll see a message to this effect.

To see what happens when a test fails, insert the line Assert.IsTrue(1 > 2); in the TestMethod1 method and run the test again. The condition is clearly false, so the test will fail, and the Test Explorer tells you this, along with which test failed.

Since we’ll be testing code we’ve written in the original ComicShop project, the ComicShop.UnitTests project needs access to that code, which it doesn’t have at the moment. To rectify this, right-click on References in the ComicShop.UnitTests project and then Add reference. Expand the Solution node and under Projects, select the ComicShop project and add it.

We now have enough material to be able to add unit tests to our existing code. However, the code as it stands isn’t in quite the right form for ‘proper’ unit testing. The reason is that the controller code we wrote in earlier posts has a direct link with the database used to store the comic book data. Thus any unit test we write for a controller method will involve connecting to the database. You might think that any proper test would have to do this anyway; after all, the program connects to the database so surely any test would also have to do this.

The point is that there are really two distinct operations involved in the controller method as it stands. First, there is the connection to, and interaction with, the database. Second, there is the logic in the controlller method itself; that is, the logic that determines what the controller does with the data it gets from the database (or sends to it, if we’re adding a new comic book). We’d really like to test these two things separately.

We’ll see in the next post how to decouple the controller from the database, but for now, just to get used to writing a unit test, we can write a simple unit test with the controller code as it stands. As a reminder, here’s the code for the Index() method in the HomeController.

    private ComicContext database = new ComicContext("ComicContextDb");
    public ActionResult Index()
    {
      var comics = database.ComicBooks.Select(book => book).OrderBy(book => book.Title);
      var model = comics.ToList();
      return View("IndexModel", model);
    }

We’ll test that the ActionResult returned at the end isn’t null.

It’s a good idea to mirror the the original application’s code structure in the unit test code structure, so we’d like tests on HomeController to be in a Controllers namespace within ComicShop.UnitTests. To do this, right-click on the ComicShop.UnitTests project and select Add–>Add folder, then name this folder Controllers. Right-click on the Controllers folder and then on Add–>Unit test. Name the new test HomeControllerTests. (Do not click on Add–>Class to add the test, since the resulting class won’t be included in the tests.)

Here’s the complete class that does our simple test.

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ComicShop.Controllers;
using System.Web.Mvc;

namespace ComicShop.UnitTests.Controllers
{
  [TestClass]
  public class HomeControllerTests
  {
    [TestMethod]
    public void Index_ValidView()
    {
      HomeController homeController = new HomeController();
      var result = homeController.Index();
      Assert.IsNotNull(result);
    }
  }
}

We create a HomeController object, call its Index() method and save the returned value in ‘result’. We then apply one of the static methods in the Assert class (one of the provided UnitTesting classes). As you can see from the Intellisense, there are a lot of tests in Assert. This one does just as it says: it tests if ‘result’ is null.

Before we leave this introductory post, it’s worth pointing out that any method that is to be used as a TestMethod must be void (return nothing) and have no parameters. The unit test must be completely encapsulated within the code for that method.

In order to test anything more significant than this, we should really restructure our code so that we decouple the controller from the database, but that’s a topic for the next post.

MVC – common layouts

In the simple example of a comic shop we’ve looked at so far, we’ve created a couple of very basic web pages using MVC 4 and Visual Studio. Many web sites have a ‘look and feel’ that is common to all their pages. There are two separate aspects to this look and feel. One consists of things like the colour scheme, font types and sizes for various headers and text, background images and so on. These things are usually specified in a CSS (cascading style sheet) file, and that’s not what we’ll look at here.

The other aspect consists of features such as headers and footers that appear on every page. These features are a matter of content rather than style, and as such, aren’t specified by a CSS file. It’s these features we’ll be concerned with here.

MVC allows us to create shared views, that is, views which are common to more than one page. One commonly used shared view is the layout view. When we create an empty MVC project, as we did in creating the comic shop site, there are, as you might expect, no shared views or layout files created, so we need to create our own. (If you selected one of the ready-made applications when you create the project, you would get a layout (and a CSS file) created for you, but it usually requires some extensive modifications to customize it for your own site, so it’s a good idea to start from scratch to get an idea of how these files are structured.)

First, we need to tell the server where to look for a layout file. If you’re using the Razor view engine (which is standard for MVC 4 sites), the construction of a view begins with a reference to a file called _ViewStart.cshtml, which is located in the top level of the Views folder. An empty project won’t have this file, and if it doesn’t exist, Razor just carries on to the requested view and builds it on its own.

So the first thing to do is to create this file. In Solution Explorer, right click on the Views node and select Add –> View, then give the name of the view as _ViewStart (note the underscore at the start). Uncheck the “Use a layout or master page” box and then click the Add button.

Delete all the code in this file and replace it with:

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

This tells Razor where the layout file is found. If you try running your web site now, you’ll get a ‘file not found’ error in the browser, which shows you that Razor is indeed looking for this layout file.

The next step is to create this file. First, we need to create the Shared folder, so right-click on Views in Solution Explorer and then Add –> New folder. Name the folder Shared.

Now right click on the Shared folder and add a view called _Layout (again, note the leading underscore). You’ll get a file with the following code in it:

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>_Layout</title>
</head>
<body>
    <div>

    </div>
</body>
</html>

If you now try to run your web site, you’ll get an error message saying that the “RenderBody” method has not been called. RenderBody() is the method that, not surprisingly, renders the body of the page, and without it, you wouldn’t get any of your view code displayed. To fix this, insert the line

@RenderBody()

at line 14 in the file. That is, put it inside the <div> tag within the <body> of the layout. Run your web site again and if all goes well, you should see the same page we had in the last post, with a list of comics in the database.

So far, we haven’t actually added anything to the site. However, now we can start to see the power of the _Layout file. Suppose we want a common header such as “Comic Shop” to appear on all our pages. We could type this header in every View file, but that’s very repetitive and error-prone. A better way is to insert this common content into the _Layout file.

For example, to have a common header on all our pages, we can insert the line

<h2>Comic Shop</h2>

after the opening <body> tag on line 12. Open the home page and you’ll see that this header appears on your page. Go to the Add page (where you can add a comic to the database) and you’ll see the same header appears there too.

Note that in order for _Layout to be applied to a view, that view must be created with the “Use a layout or master page” box checked. As it says in the dialog, leave the name of the layout page blank if you’ve specified it in the _ViewStart file as described above.

We can insert all sorts of stuff into the _Layout file to create as complex a common layout as we like, but you get the idea. (As another example, you might want to change the title of the page to ‘Comics’ by changing line 10.)

MVC – strongly typed views

In MVC4, we’ve seen that we can send data from the controller to a view by using the ViewBag, which is a dynamic C# object in which you can define properties of any data type.

Although this is a powerful technique, you might have noticed if you were typing in the code we gave in the last post for displaying the list of comic books in the view that Visual Studio’s Intellisense didn’t seem to be working. Here’s the code we typed in the last post:

<ul>
    @foreach (var comic in ViewBag.Comics)
    {
        <li>
                @comic.Title: <b>@comic.Volume</b> (@comic.Issue)
        </li>
    }
</ul>

The Comics property of the ViewBag was of type List<Book> (where Book is a model class that contains the properties of a comic book), so the foreach loop accesses each Book in turn and prints out its fields on the web page.

When you type the @comic. bit, ordinarily you’d expect Intellisense to pop up with a list of fields in the Book object, but here nothing happens. This is because VS has no way of knowing what the data type of ViewBag.Comics is until the program is actually run. That’s part of the beauty of a dynamic variable, but it also means that coding is more difficult.

A way around this is to use a strongly-typed view. We’ll pass the same data (a List<Book>) to the view, but we’ll do it in a way that lets the view know the data type of the object that is being sent to it.

The changes we need to make to the code are minimal, but the effect is profound. To begin, we’ll change the Index() method in HomeController:

    private ComicContext database = new ComicContext("ComicContextDb");
    public ActionResult Index()
    {
      var comics = database.ComicBooks.Select(book => book).OrderBy(book => book.Title);
      var model = comics.ToList();
      return View("IndexModel", model);
    }

The only change we made is the last line of the method, where instead of assigning the ‘comics’ list to the ViewBag, we pass it directly to the view as an argument in the View() method.

We’ve also specified that the view that should be called is named “IndexModel”, rather than the default “Index” that we used before. This is simply so we can have two alternative views for the same controller action. In a finished application, you’d probably choose one or the other and delete the other one.

You can use VS’s wizard to create this new view class. Right-click on the Index() method in the controller and select ‘Add view’. In the dialog, select ‘Create a strongly-typed view’ and give List<Book> as the model class.

Here’s the contents of IndexModel.cshtml:

@using ComicShop.Models
@model List<Book>

<h2>Comics</h2>

<ul>
    @foreach (var comic in @Model)
    {
        <li>
                @comic.Title: <b>@comic.Volume</b> (@comic.Issue)
        </li>
    }
</ul>

Note the two lines at the top. First, we have a ‘using’ statement which works the same as in regular C# code: we’re telling the view that we’ll be using classes in the ComicShop.Models namespace.

The second line is the key to creating a strongly-typed view. We specify that the model object is of type List<Book>. (This line will be inserted for you if you used the wizard to create the view as specified above.)

The foreach loop now loops over the elements in @Model rather than ViewBag.Model. If you type in the contents of the loop, now you’ll notice that Intellisense does work: you’ll get a list of properties of each comic object as you type.

The output of this page is the same as the earlier view. The only difference is how we’ve managed to interaction between the controller and the view. Besides enabling Intellisense, a strongly-typed view enables the compiler to check your code.

Or at least it should. In VS2012, if you type an incorrect name for a model property, an error is flagged in the editor (a squiggly red line appears under the incorrect name), but the project, somewhat confusingly, will still build. Of course when you try to run it, you’ll get an error page in the web browser.

You also need to be careful if you want to refactor your model class. For example, if you wanted to change the name of the Title property to something else like Header by using VS’s refactoring tool, it will change the property’s name in all the C# code, but not in the view code. Again, the error will be flagged up in the editor, but the project will still build (and of course, not run). Caution is required!

MVC 4 – Displaying data

We’ve seen how to add a database to an MVC 4 project, and how to enter data from a web page and store it in the database. Here we’ll look at how to retrieve the data and display it on a web page.

Having set up the database machinery before, retrieving the data is quite easy. We’ll retrieve the list of comic books that we’ve entered into the database and display it on the home page of the site. To that end, we change the HomeController’s Index() method so it looks like this:

    private ComicContext database = new ComicContext("ComicContextDb");
    public ActionResult Index()
    {
      var comics = database.ComicBooks.Select(book => book).OrderBy(book => book.Title);
      ViewBag.Comics = comics.ToList();
      return View();
    }

The database is accessed using the same method we discussed in the post on adding a database.

The DbSet field, ComicBooks, in the ComicContext class represents a data set on which we can run LINQ queries. Here, we’ve done a simple query that selects all the entries in the DbSet and sorts them by the Title field.

Having retrieved the data, we need a way of sending the data to the view so it can be displayed. The ViewBag is a C# dynamic variable (on which I hope to post soon). The data type of a dynamic variable can change as the program runs. In particular, we can define data fields for this variable at runtime rather than compile time, which is what is done here. We’ve defined a Comics field for the ViewBag and assigned it the result of the LINQ query converted to a List.

The ViewBag is a utility variable which is available in the View class, and is a ‘bag’ into which we can throw any data we want the view to display. You might think that this sort of thing can rapidly get out of hand; after all, we could throw loads of data into the ViewBag and lose any pretense of a well-structured program.

This is true, but then a well-designed web page shouldn’t display too much on one page anyway, so if we’re writing a decent web site, there shouldn’t be any need to throw too much data into the ViewBag.

So much for the controller. Now we need to look at the view. The View file for Home’s Index action is:

<h2>Comics</h2>

<ul>
    @foreach (var comic in ViewBag.Comics)
    {
        <li>
                @comic.Title: <b>@comic.Volume</b> (@comic.Issue)
        </li>
    }
</ul>

After the header is printed, we define an unordered list. We can embed C# code in the HTML by prefixing a line or element of code with the @ sign. Thus we have a foreach loop which runs over ViewBag.Comics (imported from the controller) and, for each comic in the list, prints out the comic’s Title, Volume and Issue fields. The output, assuming we’ve entered 3 comics, looks like this:

 

The volume number is printed in bold, and the issue is surrounded by parentheses (so the parentheses around @comic.Issue are printed out; they’re not part of the C# code).

That’s really all there is to accessing and displaying data, although of course there are a lot of other things you can do to add bells and whistles.

MVC 4 – Adding a database

In the last post, we saw how to set up an MVC4 web site in Visual Studio 2012, and how to add a simple controller and view to it.

Most web sites that do anything more than display a bit of fixed information have a database behind them. For example, a blog is backed by a database that stores the posts, a shop contains information on products available in a database and so on.

In this post, we’ll expand our ComicShop site so it contains a database that stores information about comics in stock. There are many databases available, but for now we’ll take the easiest route and use SQL Server Compact Edition, which is included with VS2012. This database has the advantage that it doesn’t require a separate server running in the background; it stores its data in a local file and accesses this file whenever it needs to update the data.

Most of the web sites and books I looked at contained instructions for installing a SQL Server CE database and connecting it with an MVC4 project, but unfortunately, if you start from an Empty project in VS2012, these methods didn’t work: the first attempt to access the database threw an exception complaining that it was unable to attach the database file.

Eventually I tracked down the problem, so in this post I’ll show how to connect a simple database to an MVC4 project.

We’ll begin by creating the database, and then add a controller and a view that allows us to add data to it.

Starting with our ComicShop project from the last post, in Solution Explorer, right-click on App_Data and select Add –> SQL Server Compact 4.0 Local Database. Name this database ComicBooks. You should see a database appear under the App_Data folder. Double-click on this file to open the Server Explorer. Open the ComicBooks node and right-click on Tables, then select Create Table. In the dialog that appears, name the table Books.

Now create some columns in this table, as follows. First, we create a primary key for the table, which we’ll call Id. Enter Id as the column name, set its Data Type to int, then set Primary Key to Yes and Unique to Yes. (The Allow Nulls value should automatically become No during this process.) In the box at the bottom of the dialog, set its Identity to True. This will make Id an auto-incrementing field, so every time you add a record to the table, Id will automatically increase by 1.

Now add a Title column, setting its Data Type to nvarchar, then a Volume column, setting its Data Type to int. Then Issue, also an int. Finally, add a Publisher column, setting its data type to nvarchar. Click on OK to close the dialog.

Just to verify that the table has been created properly, open the Tables node in Server Explorer, right-click on the Books table and select Show Table Data. You should see a window showing one row with the columns you just defined, each containing a NULL entry.

Now that we have our database defined, we need a way of putting data into it. One way is to edit the data table in the Show Data Table window directly, but that obviously isn’t much use if you want to edit the data via the web site. So we need to add a controller and view that allows access to the database via a web page.

First, we need a class to store the data fields for a single comic book. This class will mirror the structure of the database. Since it stores data, it belongs in the Models folder, so right-click on Models in Solution Explorer and select Add–>Class. Call the class Book, and enter some properties to match those in the database:

namespace ComicShop.Models
{
  public class Book
  {
    public int Id { get; set; }
    public string Title { get; set; }
    public int Volume { get; set; }
    public int Issue { get; set; }
    public string Publisher { get; set; }
  }
}

Next, we need a way of connecting the C# code to the database. The easiest way (well, after we know what to do…it took a lot of searching to find the right way of doing it!) is to use a DbContext. Add another class called ComicContext to the Models folder, with code as follows (I’ll explain this code in more detail later):

using System.Data.Entity;

namespace ComicShop.Models
{
  public class ComicContext : DbContext
  {
    public ComicContext(string conn)
      : base(conn)
    {
    }

    public DbSet<Book> ComicBooks { get; set; }
  }
}

You will notice that VS complains that System.Data.Entity doesn’t exist. You might think that the usual solution of adding this namespace in your References list will fix the problem, but even though System.Data.Entity does exist in the list of assemblies you can add to References, adding it doesn’t help much: VS still complains that it can’t find DbContext (even though the online documentation says that it is part of System.Data.Entity).

The solution turns out to require the addition of a NuGet package. To do this, right-click on References in Solution Explorer and select Manage NuGet Packages (if this option doesn’t exist, you’ll need to install NuGet from nuget.org). Select Online on the left, and enter EntityFramework in the search box in the upper right. After the search engine finds it, check that it’s version 5.0.0 of EntityFramework, then click on Install. At this point, everything should compile properly. (For the curious, EntityFramework is a huge topic in its own right, so we won’t go into that here.)

We also need to install another NuGet package to allow us to use SQL Server CE, so while you’ve got NuGet open, do a search for EntityFramework.SqlServerCompact. This should return only a single result, so install that and then close the NuGet dialog.

We’ve now got the model classes set up so we need to add the controller and view to allow data to be input. Open HomeController.cs (which we created in the last post). Remember that each method in this controller corresponds to a separate URL that the user can visit in your web site. The Index() method gives the home page which we saw last time.

We want to add a page for entering data for a comic book, so we’ll write an Add() method. The code is much the same as for Index():

        public ActionResult Add()
        {
          return View();
        }

Right-click in this method and select Add View, accepting the default name of Add. We’ll keep things simple by knocking up a basic HTML form; it’s not pretty but we can worry about that later. Right now we just want to get the site working. The code is

@{
    ViewBag.Title = "Add comic";
}

<h2>Add new comic</h2>
<form method="post">
    <fieldset>
        <legend>Add comic form</legend>
        Title: <input type="text" name="Title" maxlength="100" />
        <br />
        Volume: <input type="number" name="Volume" />
        <br />
        Issue: <input type="number" name="Issue" />
        <br />
        Publisher: <input type="text" name="Publisher" />
        <br /><br />
        <input type="submit" value="Submit Comic" />
    </fieldset>
</form>

This produces four input boxes for entering the four bits of data required for a comic book, and then displays a submit button at the bottom, which returns the entered data back to the web server.

Note that we’ve named each input element so that its name matches the corresponding field in the Book class (and hence the column in the database); this is important for the connection to work properly.

The last link in the chain is the handler for the data submitted by the form. To enable communication with the database, we need to let the web server know where to find the database file. This requires adding a bit to the web.config file for the project. Open Web.config in Solution Explorer (Note that there are two web.config files, one at the top level and one inside the Views folder. It’s the top-level one we want.) At the end of the file, just above the closing </configuration> tag, insert the following:

  <connectionStrings>
    <add name="ComicContextDb" connectionString="Data Source=|DataDirectory|\ComicBooks.sdf" providerName="System.Data.SqlServerCe.4.0"/>
  </connectionStrings>

(This assumes you’ve followed the instructions above and created your database file under App_Data with the name ComicBooks.) This defines a connection to the database file called ComicContextDb, and specifies that it is a SQL Server CE database.

Now we can write the handler for the data sent back by the form. To do this, we add a bit more code to the HomeController class:

    private ComicContext database = new ComicContext("ComicContextDb");
    [HttpPost]
    public ActionResult Add(Book book)
    {
      database.ComicBooks.Add(book);
      database.SaveChanges();
      return Content("New comic added.");
    }

We create an instance of our ComicContext model class and pass it the name of the connection that we defined in web.config above. If you look at the code for ComicContext above, you’ll see that this string is passed back to the base class (DbContext), which takes care of the interaction with the database, so this base class will use the connection string to establish a link with the database.

Another important point is that the data type (in this case Book) specified in the DbSet object in ComicContext is the singular of the name of the table (Books) in the database. This is actually required in order for the link to work properly. In fact, if we had specified a different class name in DbSet, a table with that name with an ‘s’ added at the end would be created within the database automatically. In general, if you change the underlying model code that links with the database after the database has been created, you’ll need to invoke a ‘migration’ process to update the database so it is in sync with the new code. We won’t go into that here, but just be aware that making changes isn’t entirely straightforward.

Returning to our second Add() method above, note that it is prefixed by an [HttpPost] tag. This indicates that the method is a handler for data returned from the Add page via the HTTP post protocol. The returned data is used to create a Book object (by matching up the control names with the Book’s field names, as mentioned above) which is then passed into the Add() method as its parameter.

The first line of Add() adds the new Book object to the ComicBooks DbSet of the database object, and the next line saves the changes to the database itself. If you’ve done any database programming before, it’s at this point that you would normally write SQL statements for inserting a new record into the database, but the DbContext and DbSet classes do all this for you.

Finally, we return a Content object that prints a message saying “New comic added.”. Obviously in a proper web site we’d want something a bit fancier than that, but at this stage that’s all we need to see that it works.

If you now start the site running and then enter the URL localhost:36195/Home/Add, (your port number might be different), you should see the form for entering some data for a new comic book. Fill in some data and press the submit button, and if all goes well, you should see the “New comic added.” message.

We haven’t provided any way of seeing the contents of the database on the web site yet, but to verify that the comic you just entered did in fact make it into the database, you can use the Show Table Data command to look at the Books table.

 

MVC 4 – An Introduction

I’ve started looking at the MVC 4 platform for developing web sites in ASP.NET, so I’ll record my experiences as I go along.

First, an introduction to the ideas behind MVC would be useful.

MVC stands for Model-View-Controller, and is a popular design pattern used in structuring medium to large programs. Its use is not restricted to ASP.NET or to web development; in fact it’s something of an industry standard for many software development projects.

The concept is fairly simple, and is based on the idea that the main functions within a program should be separated, since this makes it easier to assign different people to different tasks, as well as making the code easier to understand and maintain.

In many programs, there is a collection of data which can be viewed in various ways. For example, in a word processor, the data consists of the text and images contained within the document. This data can be viewed in various ways: in edit mode where changes can be made, in print preview mode where the user sees what the document will look like when printed, in outline mode where only the section headers are shown, and so forth. In all these views the underlying data – the model – remains the same. Thus to put it simply, the model is the information stored in a program and the view is how it looks to the user.

The controller is a bit more vague, but in essence it’s the code that links the model to the view. In a program with various user interaction controls such as buttons and menus, the controller consists of the event handlers that process the user’s actions. For example, if the user presses the Print Preview button in a word processor, the controller processes this action by retrieving the document from the model and passing it to the view that displays a print preview.

In the particular case of MVC as applied to ASP.NET (rather confusingly, MVC can refer to the generic design pattern as used in any type of program and also to the specific implementation in ASP.NET), the model stores the data (in C# data structures or possibly in a database) and the view generates the HTML which allows the user to view the data in some form. The controller responds to a user’s request for a web page by retrieving whatever data is required from the model and then passing this to a view which constructs the web page that is sent back to the user.

That’s really about all you need to understand about MVC to get started. From here on, it’s easiest if we use an actual example to demonstrate how to build an MVC project. In what follows, I’m using Visual Studio 2012 (version 11 of Visual Studio), which has support for MVC 4 built in. If you’re using VS2010, you’ll need to download and install MVC 4 support as an add-on. This should be freely available from Microsoft’s web site – as always, Google is your friend here.

Even in VS2012, however, the first time I tried to create an MVC 4 project, I got an error saying that the NuGet package wasn’t found. This is easily fixed by visiting nuget.org and installing the package.

Assuming you’ve got VS set up properly, begin by creating a new project. In the New Project dialog, select ASP.NET MVC 4 Web Application. We’ll look at building a web site for a comic shop, so call the project ComicShop and click OK. You’ll then see the New ASP.NET MVC 4 Project dialog, which offers several options for your new project. Internet Application is pre-selected, and if you go with this you’ll get the outline of a functional web site with pages for creating accounts, logging in and so on. All of this functionality can be a bit daunting at first, so we’ll start with the Empty template.

Even with an empty project you get a fair number of files. In Solution Explorer, have a look at the folders that have been created; you’ll see among them folders for Controllers, Models and Views and as you might guess, that’s where most of your work will be done.

If you try running the project at this point by pressing Control+F5 to start without debugging, what should happen is a page will open in your default browser (I use Google Chrome, but this should work with whatever your default browser is). Visual Studio will start up a local web server for the purposes of testing your project and attempt to display the home page of this site in the browser.

At this stage you’ll get an error message saying the the page at ‘/’ (the root of the web site) couldn’t be found. This isn’t terribly surprising, since we haven’t added any pages to the site yet.

So where do we start? First we need to understand a bit about how MVC handles naming conventions. The conventional name for a controller class is <Path>Controller, where <Path> is the part of the URL following the site’s address. For example, with the local server created by VS, the home page might have the URL localhost:30844/Home/Index. In this case, the controller class that handles the request for the page is HomeController. (We’ll deal with the Index part in a minute.)

Let’s add a controller to the project in an attempt to get a home page. In Solution Explorer, right-click on the Controllers folder and select Add –> Controller. In the dialog that appears, name the controller HomeController and select Empty MVC controller for the template, then click Add. You’ll see the file HomeController.cs appear in the Controllers folder, and the class file will be displayed in the code editor. It should look like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace ComicShop.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/

        public ActionResult Index()
        {
            return View();
        }

    }
}

Before we explain anything, try running your project again. You’ll still get an error, but this time it’s complaining that it can’t find a view. To fix this, right-click on the Index() method and select Add view. Accept the default name of Index and click Add. You’ll see another file appear in the code editor, but ignore that for now. Now try running the project again.

This time, you should get a page in the browser with the word ‘Index’ in a big, bold font at the top. Congratulations – you now have a functioning web site! OK, it’s not particularly informative, but it’s a start.

Now for a bit of explanation as to what has happened. The most obvious question is probably: How did the web server know to display the page with Index on it? After all, we could have called our controller anything at all, and not just HomeController, and we never specified Home in the browser – the page just magically appeared.

Actually, if we had called the controller something else, it wouldn’t have worked. To see why, look in Solution Explorer and open the folder called App_Start. Inside this, open the file RouteConfig.cs. You’ll see this code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace ComicShop
{
  public class RouteConfig
  {
    public static void RegisterRoutes(RouteCollection routes)
    {
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

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

The routes.MapRoute() call defines what the default URL will be. The ‘url’ parameter says that the default format for a URL is “{controller}/{action}/{id}”, and the ‘defaults’ line says the default controller name is Home and the default action name is Index. The last entry says that ‘id’ is optional.

What this means is that if we don’t specify a URL, the request to the server is taken to be for the page /Home/Index, and that the controller called HomeController should be called for this. Within this controller, the action called Index should be called. (The ‘id’ is an optional bit of information we can tack on to the URL, but more on that later.)

What is happening, then, is that the server is started up and looks for a controller called HomeController and then for an action called Index within that controller.

That action, at the moment, returns the result of a call to View(), and as you’ve probably guessed, that uses the code in the Index.cshtml file that you created above when you added a view to the Index() method to generate the HTML which is sent back to the browser. If you know a bit of HTML syntax, you’ll see that all this page does is print Index, which is in fact what you’ve seen.