CHAPTER 13 ASP.NET MVC 318 namespace Chapter13.BobsMoviesMVC.Controllers { public static class UrlHelperExtension { public static string AllFilms(this UrlHelper helper) { return helper.Content("~/Film/All"); } } } You can then use this as follows: <a href="<%= Url.AllFilms() %>">All Films</a> Filters ASP.NET MVC allows the creation of reusable blocks of code called filters that intercept and process various types of requests. Common uses of filters include authorization and logging. For information on overriding controller classes and views, see the “Further Reading” section at the end of the chapter. Testing Of course, one of the biggest advantages of MVC is its testability, and no overview of ASP.NET MVC would be complete without looking at this functionality. Note that this functionality is not available in all versions of Visual Studio. An alternative is to use an open source framework such as NUnit (which is arguably much better supported and documented, anyway). Creating a Fake Film Repository To avoid accessing the database, you will create a fake class to return films: 1. Create a new folder in the project called Support. 2. Add a new class called FakeFilmRepository. 3. Replace the code in FakeFilmRepository.cs with the following: using System; using System.Collections.Generic; using System.Linq; using System.Web; using Chapter13.BobsMoviesMVC.Models; CHAPTER 13 ASP.NET MVC 319 namespace BobsMoviesMVC.Support { public class FakeFilmRepository : IFilmRepository { public List<Film> Films = new List<Film>(); #region IFilmRepository Members public bool Add(Film film) { throw new NotImplementedException(); } public Film Create() { throw new NotImplementedException(); } public void Delete(int ID) { throw new NotImplementedException(); } public IEnumerable<Film> GetAll() { return Films; } public Film GetFilm(int FilmID) { return Films.Single(f => f.FilmID == FilmID); } public void Save() { throw new NotImplementedException(); } public bool Update(Film film) { throw new NotImplementedException(); } #endregion } } Creating a Test When you first created the project, VisualStudio asked whether you wanted to created a test project. Hopefully, you selected Yes, so you should have two projects in your solution. CHAPTER 13 ASP.NET MVC 320 1. Open the project named Chapter13.BobsMoviesMVC.Test. 2. Right-click the Controllers folder and select Add New ItemClass. Call it FilmControllerTest. 3. Enter the following code for the test: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.Mvc; using Microsoft.VisualStudio.TestTools.UnitTesting; using BobsMoviesMVC; using Chapter13.BobsMoviesMVC.Controllers; using Chapter13.BobsMoviesMVC.Models; namespace BobsMoviesMVC.Tests.Controllers { [TestClass] public class FilmControllerTest { [TestMethod] public void All_Action_Should_Return_All_View() { FilmController controller = new FilmController(GetFakeRepository()); ViewResult result = controller.All() as ViewResult; Assert.IsNotNull(result); } [TestMethod] public void Test_To_Show_What_Failed_Test_Looks_Like() { Assert.IsTrue(1 == 2); } [TestMethod] public void Detail_Action_Should_Return_Specific_Film_Matching_ID() { FilmController controller = new FilmController(GetFakeRepository()); ViewResult result = controller.Detail(1) as ViewResult; Assert.IsTrue(result.ViewData["title"].ToString() == "Test film"); } [TestMethod] public void Film_Should_NotValidate_With_No_Title() { Film Film= new Film(); Film.Title = ""; Assert.IsTrue(Film.IsValid() == false); } private BobsMoviesMVC.Support.FakeFilmRepository GetFakeRepository() { CHAPTER 13 ASP.NET MVC 321 //Set up pretend repository BobsMoviesMVC.Support.FakeFilmRepository PretendRepository = new BobsMoviesMVC.Support.FakeFilmRepository(); //Add a film to pretend repository PretendRepository.Films.Add(new Film { FilmID = 1, Title = "Test film" }); return PretendRepository; } } } Modify Film Controller You now need to tell the Film controller to make use of the FakeFilmReposiory. Open FilmController and add the following constructor to allow you to inject the fake repository: public FilmController(BobsMoviesMVC.Models.IFilmRepository Repository) { filmRepository = Repository; } Running Tests You can run tests in a number of ways. One way is to open the test window: 1. Select Test on the main menu; then choose WindowsTest View. 2. Select the test Film_Should_NotValidate_With_No_Title. 3. Right-click it and select Run selection. After the test has run, a dialog indicating the current status will be displayed (see Figure 13-9). Figure 13-9. VisualStudio test results dialog CHAPTER 13 ASP.NET MVC 322 ASP.NET MVC V2 At the time of writing, VS2010 includes a preview of ASP.NET MVC V2, the second generation of ASP.NET MVC. Microsoft says that the final release of ASP.NET MVC 2 is expected to contain the following new features: • Areas that allow you to group controllers and views • New annotation attributes for validation logic • New Html.EditorFor and Html.DisplayFor methods ASP.NET MVC in the real world I asked a few developers about their experiences with using the ASP.NET MVC. Below is Jeremy Skinner’s (a member of the MVC contrib project) experience with developing a site for college applications using ASP.NET MVC: Although we have now developed several systems with ASP.NET MVC, one of the most successful is the online application form that allows students to apply to our college via the web and then subsequently track the progress of their application. Despite being given short notice for the development of this project, we were able to implement it quickly thanks to the simplicity of the framework. The system was a resounding success and received over 1200 applications within the first 15 minutes of going live. I've been working with the ASP.NET MVC framework since its first public preview in late 2007. Since that time I've developed several intranet applications and two public facing websites with the framework. While ASP.NET MVC may not be suitable for everyone, I personally have found the framework's lightweight and stateless approach to web development a much more natural way of working than the pseudo-stateful approach used by ASP.NET Web Forms. However, using the framework so early in its development cycle had several problems. Firstly, the early previews contained a lot of breaking changes from release to release as its API evolved. This caused a lot of frustration as it constantly meant re-writing sections of our applications, but this is the price of being an early adopter. On top of this, there was initially a lack of publicly available documentation on the framework but thankfully the source code was available which made it possible to diagnose issues with relative ease. CHAPTER 13 ASP.NET MVC 323 The MVC framework's simplicity was also somewhat of a curseits focus on lightweight HTML-driven views (rather than the control-centric model of Web Forms) meant that the majority of existing ASP.NET controls and components were not re- usable with ASP.NET MVC. However, a community quickly sprang up to address this issue and I contributed several components to the open source MvcContrib project (http://mvccontrib.org). Despite these initial shortcomings the experience has been largely positive. The MVC framework has helped to address some of the pain points that I encountered when working with Web Forms. For example, being a practitioner of Test Driven Development, I have found the framework's focus on testability has meant that we could be easily integrate it into our development process without the need to write layers of abstraction to ease testing. In addition, the framework's relatively open nature has meant that we have been able to extend and replace areas of functionality where the default behavior has been unsuitable for our needs. I plan to continue using the MVC framework for developing web applications on the Microsoft platform going forward. You can view the finished site at http://www.farnborough.ac.uk/. Jeremy Skinner http://www.jeremyskinner.co.uk What’s Next? When you start writing real-world MVC applications you will probably find you have a number of questions about the best way to design your applications (which is somewhat ironic given that MVC stresses convention over configuration). When dealing with design decision, it can help to bear the following ideals in mind: • Aim for a thin controller and fat modelthe controller is just responsible for interacting with the View and Model, and should never contain any logic! Okay, you haven’t been that strict in this chapter, but you should because it will make your applications much easier to test. • Consider whether your application could be easily split or load-balanced across a number of servers easily. If it can, the chances are good that your architecture is pretty clean. If, however, you are storing data in session, you might want to reconsider your approach. • ASP.NET MVC is a framework to be built on. It allows you access to the raw metal but this comes at a price: lack of inbuilt functionality! You will want to take a look into the MVC Contrib project that adds some very useful additional functionality: http://www.codeplex.com/MVCContrib. • In the example, you used dependency injection techniques. Read up on this and IOC containers such as Castle Windsor. CHAPTER 13 ASP.NET MVC 324 ASP.NET MVC Highlights Here are some of the highlights of ASP.NET MVC: • ASP.NET MVC’s seperation of concerns eases testability. • Complete control over rendered HTML. • If you adhere to MVC’s guidlines, you have the flexibility of being able to alter your UI, business logic, or database without affecting other layers. • Control over your application's URL, which can aid with search engine indexability and can make your application easier to navigate (note routing functionality is available in ASP.NET 4). • ASP.NET MVC offers better performance than ASP.NET. • ASP.NET MVC follows the stateless nature of the Web, which can make it easier to scale out applications and for integration purposes. • Works well with a test-driven development approach. • Integrates well with JavaScript frameworks. Considerations Take the following into account before choosing ASP.NET MVC: • ASP.NET MVC is a radically different approach to web development, so do not underestimate the time it will take developers to adapt to it. Additionally, developers will need familiarity and be able to understand some more advanced concepts such as loosely coupled applications and IOC. • ASP.NET MVC is a framework to build upon; it will probably not contain all the functionality you require. • ASP.NET MVC is unsuitable if your existing code makes extensive use of ViewState. • ASP.NET can make creating custom controls much harder. • Many third-party ASP.NET controls will not be compatible with ASP.NET MVC (note that some vendors have released ASP.NET MVC control suites already). • ASP.NET MVC can increase application development time. • Developers coming from a winforms background might find ASP.NET easier to similarities in event models. • Some developers feel that ASP.NET MVC is going back to the days of ASP classic and do not like the “tag soup” that pages can become. • ASP.NET MVC is still in its infancy, and other more mature alternatives exist. Perhaps the most popular is on the .NET platform is MonoRail (http://www.castleproject.org/monorail/ (note the similarities between ASP.NET MVC and Monorail). Another rising star is OpenRasta (http://www.openrasta.com), which is “an MVC framework with a focus on REST.” • People get really religious about ASP.NET versus MVC approaches! CHAPTER 13 ASP.NET MVC 325 Summary Developers seem to either love or hate MVC. Both MVC and ASP.NET have a number of advantages for different scenarios. Learn when each is appropriate. Further Reading A number of links and books to further explore MVC include the following: • Pro ASP.NET MVC Framework, by Steven Sanderson (Apress). A great in depth look at ASP.NET MVC utilizing Castle suite and delves deep. Also take a look at the author’s site at http://blog.codeville.net/. • Professional ASP.NET MVC by Scott Hanselman (Wrox). This is a very readable introduction to ASP.NET MVC that I very much enjoyed. Advanced users might find this book doesn’t delve deep enough, however, and be better served by Steven Sanderson’s book. • http://haacked.com/. Phil Haack is a program manager at Microsoft, currently working on ASP.NET MVC framework. He often posts ASP.NET MVC–related articles. • http://folk.uio.no/trygver/1979/mvc-1/1979-05-MVC.pdf. Original document that lead to MVC. . 13-9. Visual Studio test results dialog CHAPTER 13 ASP .NET MVC 322 ASP .NET MVC V2 At the time of writing, VS 201 0 includes a preview of ASP .NET MVC V2, the second generation of ASP .NET MVC and received over 1 200 applications within the first 15 minutes of going live. I've been working with the ASP .NET MVC framework since its first public preview in late 200 7. Since that time. containers such as Castle Windsor. CHAPTER 13 ASP .NET MVC 3 24 ASP .NET MVC Highlights Here are some of the highlights of ASP .NET MVC: • ASP .NET MVC’s seperation of concerns eases testability.