[this post is outdated – too much has happened since the first CTP]
This is the first post in a series of at least four about ASP.NET MVC, which I am planning. The series will show a way to build a nifty web site with a tidy, sound, and scalable architecture. ASP.NET MVC will be used to structure the web site, Castle ActiveRecord will be used for persistence, Castle Windsor for dependency injection, NUnit and NMock for testing, NHaml for the views, and principles from agile, domain-driven design, and test-driven development will be used. The series assumes that you want to use the model-view-controller pattern, so I will not try to convince you that it is a great way to structure a web site 🙂 – even though it is, and currently in my opinion the only sane way to make websites when they contain more than one page…
ASP.NET MVC is a part of the ASP.NET 3.5 Extensions, which is currently only available as a preview. Thus, the details might turn out to be a little off, but still most of the stuff we go through here will apply.
As this is the first post in the series, we will start out by creating a the solution and the project structure – just to get going.
Step 1: Installing the extensions and creating a solution.
First we start out by installing the ASP.NET 3.5 Extensions – just follow the link above. The extensions require that the .NET 3.5 framework is installed on your computer, and I assume that you are using Visual Studio 2008. Originally, I started out wanting to use Visual Web Developer 2008 Express, because I thought it was really cool of Microsoft to give away free editions of Visual Studio – but then I found out that Web Developer is a severely crippled version of VS, as its solutions can only contain one web site. That’s right! You cannot add another project to a Web Developer solution…! That, in my opinion, renders the Web Developer Express unusable to professionals!
I thought about using Web Developer in conjunction with Visual C# Express then, and then make all my projects in Visual C# Express, importing the DLL’s into my bin folder in Web Developer. This would probably turn out to be an annoying process, but perhaps it is actually a viable solution to getting started using only the free editions of VS.
But for now, I assume we are using the real Visual Studio 2008.
After installing the extensions, you will get access to a few additional project templates in VS. The interesting ones are the “ASP.NET MVC Web Application” and “ASP.NET MVC Web Application and Test”.
We will choose the first option – i.e. without Microsoft’s own test framework. There is probably nothing wrong with their test framework, it’s just annoying that they go ahead and make their own implementation when there are so many great open source alternatives out there. Sometimes it’s like they refuse to acknowledge that there is an open source world. We will use NUnit when the time comes to test our code (i.e. in a few minutes actually 🙂 ). To be fair however, I must mention the fact that the final project template will feature this dialog – allowing you to choose between a dozen or so test frameworks to use.
Step 2: Creating our domain model project.
As you can see, there are folder for models, views and controllers. But there is a caveat: you should not put your domain model inside the Models directory! We want to apply an ounce of DDD here, so we put the domain model in a (relatively) persistance ignorant project. It’s not going to be completely PI however, as we are going to add attributes to all our entity classes to allow ActiveRecord to figure things out.
So you might as well go ahead and delete the Models folder – we will not need it. Instead, go ahead and add a new project of the type “Class Library” to your solution. Delete that silly “Class1.cs” file, which is always generated.
Step 3: Creating a test project.
Now we want to create a project, which we will use to test stuff. To make things easy, we use it to test our controllers AND our domain model, even though it would have been nicer to separate the domain model tests from anything but the domain model.
So go ahead and add another new class library to the solution.
Your solution should look something like the one shown in the picture below. It can be seen that a bunch of assembly references have been added, while all the annoying LINQ references have been removed as well.
Step 4: Unit testing a controller.
Last thing we will do today is to create a unit test file for our
HomeController. Start out by adding your MVC project and your domain model project as references to your test project. Then add a folder, Controllers, which we will use to store test fixtures for each controller in the system. Add a file, TestHomeController.cs to it. Then add the
TestFixture attribute to the test class, and create the
HomeControllerDouble class deriving from
HomeController.
Having done that on my system, my VS looks like below.
The sqiggly under the HomeController class means that I need to reference the System.Web.Extensions assembly from my test project. But it seems the System.Web.Extensions assembly which is registered in the GAC is older than the one my web project references, so I make my web project do a “copy local” on the assembly, and then make my test project reference the copied assembly (which resides in /MooBlogMVCDemo/bin/ beneath my solutions folder).
Now I can build the solution. To test that my controller will render the right view, I add a couple of lines to the HomeControllerDouble subclass, like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class HomeControllerDouble : HomeController { string viewName; public string ViewName { get { return viewName; } } protected override void RenderView(string viewName, string masterName, object viewData) { this.viewName = viewName; } } |
– and then I complete the test by actually calling the Index action on my home controller and asserting that the controller want to render the right view. The test can be seen below:
1 2 3 4 5 6 7 8 9 |
[Test] public void RendersTheRightView() { HomeControllerDouble homeController = new HomeControllerDouble(); homeController.Index(); Assert.AreEqual("Index", homeController.ViewName); } |
That was the first step towards our nifty web site. We saw how to create the MVC project, add a domain model and a test project to the solution, and how to write the first controller unit test. In part two of the series we will create a simple model of a blog post and bubble it all the way up through a controller, into a view model, and into a view.