Monthly Archives: September 2012

LINQ: ToLookup

We’ve seen how to create a Dictionary using LINQ. A Dictionary is a hash table in which only one object may be stored for each key. It can also be useful to store more than one object for a given key, and for that, the C# Lookup<> (part of the System.Linq namespace) generic type can be used.

LINQ provides the ToLookup() method for creating Lookups. It works in much the same way as ToDictionary(), except that as many objects as you like can be attached to each key.

Returning to our example using Canadian prime ministers, we can create a Lookup in which the key is the first letter of the prime minister’s last name. The code is

      PrimeMinisters[] primeMinisters = PrimeMinisters.GetPrimeMinistersArray();
      var pmLookup01 = primeMinisters.ToLookup(pm => pm.lastName[0]);
      var keys01 = pmLookup01.Select(pm => pm.Key).OrderBy(key => key);
      Console.WriteLine("----->pmLookup01");
      foreach (var key in keys01)
      {
        Console.WriteLine("PMs starting with {0}", key);
        foreach (var pm in pmLookup01[key])
        {
          Console.WriteLine("  -  {0}, {1}", pm.lastName, pm.firstName);
        }
      }

This is the simplest version of ToLookup(). The method takes a single argument, which is a function specifying how to calculate the key. In this case, we just take the first char in the string pm.lastName.

For some reason, the Lookup class doesn’t contain a property for retrieving the list of keys, so we need to use a roundabout method to get them. Line 5 uses a Select() to retrieve the keys and an OrderBy() to sort them into alphabetical order. We can then iterate over the keys and, for each key, we can iterate over the prime ministers for that key. Note that the object pmLookup01[key] is not a single object; rather it contains a list of all prime ministers whose last name begins with the letter contained in the key.

The output from this code is:

----->pmLookup01
PMs starting with A
  -  Abbott, John
PMs starting with B
  -  Bowell, Mackenzie
  -  Borden, Robert
  -  Bennett, Richard
PMs starting with C
  -  Clark, Joe
  -  Campbell, Kim
  -  Chrétien, Jean
PMs starting with D
  -  Diefenbaker, John
PMs starting with H
  -  Harper, Stephen
PMs starting with L
  -  Laurier, Wilfrid
PMs starting with M
  -  Macdonald, John
  -  Mackenzie, Alexander
  -  Meighen, Arthur
  -  Mackenzie King, William
  -  Mulroney, Brian
  -  Martin, Paul
PMs starting with P
  -  Pearson, Lester
PMs starting with S
  -  St. Laurent, Louis
PMs starting with T
  -  Thompson, John
  -  Tupper, Charles
  -  Trudeau, Pierre
  -  Turner, John

We can do the same thing using the second form of ToLookup(), which allows us to specify an EqualityComparer to be used in determining which keys are equal. The comparer class looks like this:

using System.Collections.Generic;

namespace LinqObjects01
{
  class LookupComparer : IEqualityComparer<string>
  {
    public bool Equals(string x, string y)
    {
      return x[0] == y[0];
    }

    public int GetHashCode(string obj)
    {
      return obj[0].GetHashCode();
    }
  }
}

This comparer compares two strings and says they are equal if their first characters are equal. Using this class, we can apply the second form of ToLookup():

      PrimeMinisters[] primeMinisters = PrimeMinisters.GetPrimeMinistersArray();
      var pmLookup02 = primeMinisters.ToLookup(pm => pm.lastName,
        new LookupComparer());
      var keys02 = pmLookup02.Select(pm => pm.Key).OrderBy(key => key);
      Console.WriteLine("----->pmLookup02");
      foreach (var key in keys02)
      {
        Console.WriteLine("PMs starting with {0}", key[0]);
        foreach (var pm in pmLookup02[key])
        {
          Console.WriteLine("  -  {0}, {1}", pm.lastName, pm.firstName);
        }
      }

The first argument to ToLookup() now passes the entire pm.lastName, and the second argument to ToLookup() is the comparer object.

When we print out the results, we have to remember that the key for each entry in the Lookup is now the full last name of the first prime minister encountered whose name starts with a given letter. Thus if we printed out the full key, we’d get a full last name. That’s why we print out key[0] on line 8; that way we get the first letter of the name.

The third version of ToLookup() allows us to specify a custom data type to return. If we wanted just the first and last names of each prime minister, for example, we could write:

      PrimeMinisters[] primeMinisters = PrimeMinisters.GetPrimeMinistersArray();
      var pmLookup03 = primeMinisters.ToLookup(pm => pm.lastName[0],
        pm => new
        {
          lastName = pm.lastName,
          firstName = pm.firstName
        });
      var keys03 = pmLookup03.Select(pm => pm.Key).OrderBy(key => key);
      Console.WriteLine("----->pmLookup03");
      foreach (var key in keys03)
      {
        Console.WriteLine("PMs starting with {0}", key);
        foreach (var pm in pmLookup03[key])
        {
          Console.WriteLine("  -  {0}, {1}", pm.lastName, pm.firstName);
        }
      }

We’ve returned to using the first letter of the last name as the key (that is, there’s no comparer), and passed in an anonymous data type as the second argument to ToLookup(). Apart from that, the code is the same as in the first example.

Finally, the fourth version allows us to specify both a custom data type and a comparer, so we can combine that last two examples to get this:

      PrimeMinisters[] primeMinisters = PrimeMinisters.GetPrimeMinistersArray();
       var pmLookup04 = primeMinisters.ToLookup(pm => pm.lastName,
       pm => new
        {
          lastName = pm.lastName,
          firstName = pm.firstName
        },
        new LookupComparer());
       var keys04 = pmLookup04.Select(pm => pm.Key).OrderBy(key => key);
       Console.WriteLine("----->pmLookup04");
       foreach (var key in keys04)
       {
         Console.WriteLine("PMs starting with {0}", key[0]);
         foreach (var pm in pmLookup04[key])
         {
           Console.WriteLine("  -  {0}, {1}", pm.lastName, pm.firstName);
         }
       }

Now we’re back to using the full last name as the key, since the comparer does the checking for matching first letters. Just make sure you pass in the arguments in the right order: (1) choose key; (2) choose custom data type; (3) choose comparer.

Advertisements

Hyperlink columns: displaying the link in a browser

A while back I posted an article on how to use the WPF DataGridHyperlinkColumn. There, the web page referenced by the hyperlink was displayed in the application’s own window, using WPF’s internal web browser. This browser has a lot of limitations, and it’s more usual for links like these to lead to the page being displayed in the user’s favourite web browser.

This post shows the modifications we need to make to have this happen.

The first thing we need to do (assuming we don’t want the page to show up in the application’s own window as well) is convert all uses of the NavigationWindow back to a normal Window. This is fairly safe to do by using a global find and replace in Visual Studio. Typically, NavigationWindow is used only in the XAML file and in the behind code for this file (where it serves as the base class for the MainWindow class). This will prevent the web page from appearing in the application itself.

To get the link to show up in the default browser, we need to add an explicit event handler to the DataGridHyperlinkColumn. If we modify the hyperlink column we used in our earlier example of a comic book database application, the XAML now looks like this:

                                <DataGridHyperlinkColumn  Header="ComicVine" Binding="{Binding ComicVine}"
                                        ContentBinding="{Binding ComicVine, Converter={StaticResource ComicVineConverter}}"
                                          Width="67">
                                    <DataGridHyperlinkColumn.ElementStyle>
                                        <Style>
                                            <EventSetter Event="Hyperlink.Click" Handler="WebPageClick"/>
                                        </Style>
                                    </DataGridHyperlinkColumn.ElementStyle>
                                </DataGridHyperlinkColumn>

The properties of the hyperlink column itself are the same as before. The change is that we’ve added an ElementStyle section, in which we’ve provided a link to a handler for the Hyperlink.Click event. This handler is in the MainWindow class and looks like this:

    private void WebPageClick(object sender, RoutedEventArgs e)
    {
      Hyperlink link = e.OriginalSource as Hyperlink;
      Process.Start(link.NavigateUri.AbsoluteUri);
    }

This code retrieves the hyperlink that was clicked, and then starts an external process by calling Process.Start() with the hyperlink as the argument. This uses Windows’ association of file type to application, so if your default browser is, say, Google Chrome, then sending a URI to Process.Start() will cause Chrome to be started and sent the URI to display.

In order for this code to work, you’ll need a couple of ‘using’ statements at the top:

using System.Diagnostics;
using System.Windows.Documents;

That’s all there is to it.

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.

Attributes

An often-overlooked feature of C# is the attribute. You might have seen them in code you’ve looked at: they appear as what look like variable names or method calls enclosed in square brackets that appear before method or class definitions (or sometimes in other places). So what are they?

Put simply, an attribute is a way of storing information about the code within the code itself; meta-information if you like. There are several pre-defined attributes you can use, but in this post we’ll look at how you can define your own attributes.

As an example, suppose you want to store creation and modification dates for some of the methods in your code. Typically, a given method has one creation date, but could have any number of modification dates. We can store each of these dates as an attribute attached to each method.

A class used to create attribute objects must inherit the Attribute class (in the System namespace). If the class has a constructor that requires parameters, these parameters must all be primitive types (things like int, float, double, string and so on). This is due to technical aspects concerning the way attributes are stored in the code, so we won’t go into that here; just remember that you can’t pass anything other than primitive data types in an attribute’s constructor.

Since we want to store dates, this means that we can’t use a DateTime structure as a parameter directly; we’ll need to pass the day, month and year as separate int parameters. With that in mind, here’s the definition of the Created attribute class which we’ll use to store the date a method was created:

  public class Created : Attribute
  {
    public Created(int year, int month, int day)
    {
      Date = new DateTime(year, month, day);
    }

    public DateTime Date { get; set; }
  }

You’ll see that Created inherits the Attribute class, and that it has one constructor used to initialize the Date object. (There are a number of other features that can be specified when defining an attribute class, which we’ll get to in a minute. This is the simplest attribute definition, in which we accept the default values for all these features.)

With this definition, we can add a Created attribute to a method.

    [Created(2012, 6, 1)]
    public void Method_1()
    {
      // ........
    }

We put the attribute in square brackets immediately before the method to which it’s attached. The attribute code is just a call to the Created constructor, and the attribute is a Created object.

For the Modified attribute, we need the same data (a DateTime) stored, but we want to allow more than one Modified attribute for each method. The default behaviour of an attribute is to allow only a single instance of that attribute per method. However, we can override this behaviour by giving the attribute class itself an attribute. So we define our Modified attribute as follows:

  [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple=true)]
  public class Modified : Attribute
  {
    public Modified(int year, int month, int day)
    {
      Date = new DateTime(year, month, day);
    }

    public DateTime Date { get; set; }
  }

The class definition here is the same as for Created; the difference is the AttributeUsage line at the start. AttributeUsage is a System pre-defined attribute which specifies how the following attribute class is allowed to be used. This code is just another call to the AttributeUsage constructor, this time with two parameters. The first parameter specifies what C# language elements the attribute can be used with. The default is AttributeTargets.All, which applied to our Created attribute above. Here, we’ve specified that Modified can be used methods and classes, though there are several other language elements that could be specified as well.

The second parameter gives a value for AllowMultiple, which defaults to false. Since we want to allow multiple Modified attributes, we set this to true. Note that there’s no way of setting just the AllowMultiple parameter without also specifying the AttributeTargets, since AllowMultiple is always the second parameter in the constructor.

With this definition, we can now add some Modified attributes to our methods. Here is the revised code, this time with two methods:

    [Created(2012, 6, 1)]
    [Modified(2012, 6, 12), Modified(2012, 8, 27)]
    public void Method_1()
    {
      // ........
    }

    [Created(2011, 11, 14)]
    [Modified(2011, 12, 12), Modified(2012, 2, 29), Modified(2012, 4, 30)]
    public void Method_2()
    {
      // .........
    }

All this is fine, but clearly attributes aren’t much use if all we can do is define them. We need a way of accessing their values later on. This is done using C#’s reflection techniques.

Reflection allows us to access properties of the code that is running at the time. We can extract information on pretty well all levels of the code, including classes and individual methods within classes. Here’s the code for accessing and printing the attributes we defined above:

    static void Main(string[] args)
    {
      MethodInfo[] methods = typeof(Program).GetMethods();
      foreach (MethodInfo method in methods)
      {
        WriteHistory(method);
      }
    }

    public static void WriteHistory(MethodInfo method)
    {
      Console.WriteLine("History for {0}", method.Name);
      Attribute[] attrs = Attribute.GetCustomAttributes(method);
      foreach (Attribute attr in attrs)
      {
        PropertyInfo dateInfo = attr.GetType().GetProperty("Date");
        if (dateInfo != null)
        {
          Console.WriteLine("    {0}: {1}", attr.GetType(),
            ((DateTime)dateInfo.GetValue(attr)).ToString("MMM dd yyyy"));
        }
      }
    }

These two static methods are defined in the same class (called Program) as the other methods above, but we could equally well have defined them elsewhere; we’d just need to modify the code a bit to access the information.

The Main() method finds the type of the enclosing Program class and calls GetMethods() to return an array of MethodInfo objects for each method in the class. This array includes entries for the methods we’ve defined here, but it also includes methods inherited from the base class (‘object’ in this case).

We then loop through this array and pass each MethodInfo object to the WriteHistory() method.

The MethodInfo class, as its name implies, contains information on the method which it represents. In WriteHistory(), we first write out the method’s name, then we extract an array of Attribute objects for that method.

In the loop over the Attribute objects, we want to print out the value of the Date property for each attribute (whether it’s Created or Modified). In this special case, since both attributes contain a Date property, we can use  the Type class’s GetProperty() method to extract the Date property, and store the result in a PropertyInfo object.

If it finds the desired property (if the result isn’t null), we can then print out its value, where we’ve cast this to a DateTime and given the ToString() method a formatting string to make the date appears neat.

The output of this program is:

History for Method_1
    AttributeTest02.Modified: Aug 27 2012
    AttributeTest02.Modified: Jun 12 2012
    AttributeTest02.Created: Jun 01 2012
History for Method_2
    AttributeTest02.Modified: Apr 30 2012
    AttributeTest02.Created: Nov 14 2011
    AttributeTest02.Modified: Dec 12 2011
    AttributeTest02.Modified: Feb 29 2012
History for WriteHistory
History for ToString
History for Equals
History for GetHashCode
History for GetType

You can see that the attributes don’t always appear in the same order in which they were defined, so you may need to sort the output if the order is important. For example, here we’d usually like the Created attribute to appear before the Modified ones, and the Modified ones to be in chronological order. These are details we can deal with later.

Note also that the GetMethods() method returns all the methods for the Program class (apart from Main()), some of which are inherited.

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.