rickardnilsson.net is a weblog and the online home of web developer and father of three, Rickard Nilsson... More
Rickard blogs about creating software solutions using ASP.NET and agile practices.
Enabling truly easy testability with ASP.NET MVC Controllers requires a Dependency Injection container. This post is about showing a more real life example of combining Unity with ASP.NET MVC Controllers than the standard demo. Unity is the IoC Container from Microsoft Patterns & Practices and ships as a part of Enterprise Library as well as a stand alone on Codeplex.
We start with the unit test which drives the design of the controller.
[TestMethod] public void Post_PostWithSlugExists_ReturnsResultWithPostAsModel() { controllerContext.RouteData.Values.Add("slug", ValidSlug); var expected = MockRepository.GenerateStub<IBlogPost>(); var blogPosts = new[] {expected}; blogPostService.Expect(s => s.GetPostWhereSlugEquals(slug)) .Repeat.AtLeastOnce() .Return(blogPosts); var controller = CreateController();
var result = (ViewResult) controller.Post(); Assert.AreEqual(expected, result.ViewData.Model); }
Even though the test becomes a bit verbose it clearly states the intent of the controller’s Post method; given the right slug, a result is returned with a blog post as model.
In ASP.NET MVC every request starts in a controller which uses a set of dependencies to do its job. When we have applied Inversion of Control we can inject all of the controller’s dependencies either as a constructor argument or as a property setter. To fully take advantage of this technique we want the dependencies to be automatically injected without creating any of them in overloaded constructors or something like that. This is where the Controller Factory in ASP.NET MVC comes into play.
In the System.Web.Mvc namespace lives the IControllerFactory which implementation is used by the framework to create controller instances. We can use this to swap out the default one and replace it with our own controller factory which uses Unity to create controllers instead.
Instead of implementing all of the IControllerF actory functionallity we can extend the System.Web.Mvc.DefaultControllerFactory and only override what we need.< /p>
public class UnityControllerFactory : DefaultControllerFactory { private readonly IUnityContainer container;
public UnityControllerFactory(IUnityContainer container) { this.container = container; }
protected override IController GetControllerInstance(Type controllerType) { return container.Resolve(controllerType) as IController; } }
In the Global.asax, called MvcApplication in ASP.NET MVC by default, we create our Unity container and tells the MVC framework to use our UnityControllerFactory instead of the default one.
// in Global.asax.cs protected void Application_Start() { RegisterRoutes(RouteTable.Routes);
var container = new UnityContainer(); var controllerFactory = new UnityControllerFactory(container); ControllerBuilder.Current.SetControllerFactory(controllerFactory); }
To illustrate why this is so powerful we will implement a controller that handles requests for blog posts, such as the one you’re reading right now. For this example the controller only handles requests for single blog posts using the post’s slug as identity. A slug is the post’s title made url friendly (e.g. "Dependency-injection-in-ASPNET-MVC-with-Unity-IoC-Container” for this post). The PostController has a dependency on an IBlogPostService which it uses to lookup the blog post to send to the view.
public class PostController : Controller { private readonly IBlogPostService blogPostService;
public PostController(IBlogPostService blogPostService) { this.blogPostService = blogPostService; }
public ActionResult Post() { var slug = GetSlug(); var post = blogPostService.GetPostWhereSlugEquals(slug); return View(post); }
private string GetSlug() { return RouteData.GetRequiredString("slug"); } }
The Post action returns an ActionResult with the post a the model. We can use strongly-typed views to get intellisense in the aspx-file.
<%@ Page /*...*/ Inherits="ViewPage<IBlogPost>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> <%=Model.Title %> </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2><%=Model.Title %></h2> <p> <%=Model.Body %> </p> <p><%=Html.PostActionLink("Permalink", Model) %></p> <p><a href="/2009/10/10/fail">fail link</a></p> </asp:Content>
<%@ Page /*...*/ Inherits="ViewPage<IBlogPost>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
<%=Model.Title %>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2><%=Model.Title %></h2>
<p>
<%=Model.Body %>
</p>
<p><%=Html.PostActionLink("Permalink", Model) %></p>
<p><a href="/2009/10/10/fail">fail link</a></p>
Notice how the view inherits from ViewPage<IBlogPost> which is key to make the model type of IBlogPost. Then we can use the Post properties to render the blog post in the view.
Combining ASP.NET MVC with Unity or your IoC Container of choice makes your controllers much more easily testable. You only state your classes dependencies as constructor parameters or properties and the container will do the wiring for you. The gives you time to focus on the program logic and the interaction between its components.
After I posted my Code Kata Cast I received some feedback regarding the ReSharper templates I use to speed up my coding. I decided to share them with the public (like so many before me) in hope that others may benefit from them, as I do.
rickardn-resharper-templates.zip (1,44 kb)
After you’ve downloaded the zip-file and unpacked it, open Visual Studio and the ReSharper Templates Explorer: Menu –> ReSharper –> Live Templates…
Click on Import… as the screen shot below shows, and find the file “rickardn-resharper-live-templates.xml”
Then click the “File Templates” tab and repeat the procedure for the “rickardn-resharper-file-templates.xml” file.
Good luck with your katas!
Much of the legacy ASP.NET code I’ve seen is littered with calls to methods on the HttpServerUtility class,
Server.MapPath(…)
Why, if your suite has thousands of tests and many calls IO or datebases, the tests will run slowly, and the developers on the team won’t run them as often. Ultimately, you may loose your investment in automated testing because it isn’t providing the promised feedback.
If the code behind code calls Server.MapPath() it is actually calling the Server property on the Page base class which returns HttpContext.Current.Server. This is an instance of the HttpServerUtility class, which is sealed and thus pretty impossible to fake out*.
In the namespace System.Web.Abstractions, which is part of ASP.NET 3.5, lives an abstraction of the HttpServerUtility, called HttpServerUtilityBase. It has a concrete implementation named HttpServerUtilityWrapper that takes an HttpServerUtility instance as a constructor parameter, as follows:
public sealed class HttpServerUtility { // ... }
public abstract class HttpServerUtilityBase { // ... }
public class HttpServerUtilityWrapper : System.Web.HttpServerUtilityBase { public HttpServerUtilityWrapper(HttpServerUtility httpServerUtility) {} // ... }
By leveraging a simple form of dependency injection we can preserve the old code as a first step of refactoring, and using an overloaded constructor to inject the fake object in our unit test.
public class Presenter { private HttpServerUtilityBase Server; public Presenter(HttpServerUtilityBase httpServerUtility) { Server = httpServerUtility; } public Presenter() { Server = HttpContext.Current.Server; } public void PageLoad() { var path = Server.MapPath(…) } }
Now, in a unit test for the Presenter class we can inject a fake server utility, which won’t call any IO.
[Test] public void PageLoad_WhenCalled_ExpectedBehavior() { var fakeServerUtility = new HttpServerUtilityFake(); // implemented in the test suite var presenter = new Presenter(fakeServerUtility); presenter.PageLoad(); // Assert expected behavior }
Instead of implementing your own fake you can easily use your preferred isolation (mocking) framework of choice.
The goal is to isolate the class under test from all of its dependencies, weather they call IO, a database, a third party component, or even statics or touch static state. The point is that we want to assert that the class under test behaves as expected, not how the underlying framework behaves.
By leveraging the System.Web.Abstractions namespace we can preserve much of the existing ASP.NET code while covering it with tests.
_________ * Unless using TypeMock Isolator
Have you ever come across the concept of a Code Kata?
For me it really took off after reading blog posts (1, 2, 3) by Unce Bob Martin and Pragmatic Programmer Dave Thomas. The concept is really simple: how can we, as programmers, better our selves and improve our techniques and proficiency in using the tools and processes in our every day work?
The suggested solution is inspired by the martial arts kata. You learn how to implement a solution to a specific problem and you practice all the moves in the exact same order over and over again. The point is that you should know the moves so well that you forget about them and focus on improving your key strokes and the use of your tool set. The never ending goal is to perform the kata with the least amount of key strokes.
The promice is that practicing these kata's often and regularly makes you a better and more productive programmer in that you are trained to act instinctively in certain reoccurring situations.
Anyway, I've been practicing a kata based on a problem initiated by Roy Osherove and I decied to record it to get some feedback and maybe spread some knowledge on how I practice Test-driven development using ReSharper.
Calculator Code Kata Cast 1 from Rickard Nilsson on Vimeo.
Roy Osherove is giving an hands-on TDD Masterclass in the UK, September 21-25. Roy is author of "The Art of Unit Testing" (http://www.artofunittesting.com/), a leading tdd & unit testing book; he maintains a blog at http://iserializable.com (which amoung other things has critiqued tests written by Microsoft for asp.net MVC - check out the testreviews category) and has recently been on the Scott Hanselman podcast (http://bit.ly/psgYO) where he educated Scott on best practices in Unit Testing techniques. For a further insight into Roy's style, be sure to also check out Roy's talk at the recent Norwegian Developer's Conference (http://bit.ly/NuJVa). Full Details here: http://bbits.co.uk/tddmasterclass bbits are holding a raffle for a free ticket for the event. To be eligible to win the ticket (worth £2395!) you MUST paste this text, including all links, into your blog and email Ian@bbits.co.ukwith the url to the blog entry. The draw will be made on September 1st and the winner informed by email and on bbits.co.uk/blog
Roy Osherove is giving an hands-on TDD Masterclass in the UK, September 21-25. Roy is author of "The Art of Unit Testing" (http://www.artofunittesting.com/), a leading tdd & unit testing book; he maintains a blog at http://iserializable.com (which amoung other things has critiqued tests written by Microsoft for asp.net MVC - check out the testreviews category) and has recently been on the Scott Hanselman podcast (http://bit.ly/psgYO) where he educated Scott on best practices in Unit Testing techniques. For a further insight into Roy's style, be sure to also check out Roy's talk at the recent Norwegian Developer's Conference (http://bit.ly/NuJVa).
Full Details here: http://bbits.co.uk/tddmasterclass
bbits are holding a raffle for a free ticket for the event. To be eligible to win the ticket (worth £2395!) you MUST paste this text, including all links, into your blog and email Ian@bbits.co.ukwith the url to the blog entry. The draw will be made on September 1st and the winner informed by email and on bbits.co.uk/blog
Have you ever wanted to rename a namespace but you have too many classes in the namespace that it would be an infeasible hassle changing all of them individually. Even using a tool like ReSharper to refactor the namespaces class by class is a hassle. I'm gonna show how to rename a namespace for all of its classes in a couple of key strokes using ReSharper.
and you're done!
Please leave a comment if you found this useful.
* Visual Studio scheme
BlogEngine.NET has a widget framework from version 1.4 which are web part like components that can be added and removed, configured and dragged around directly in the page. Simple widgets are very easy to create and plug in to your blog and there are several blog posts explaining how to do that. In this post I'm gonna go through a more advanced example featuring Web services and Ajax.
The Photo Album Widget
Download: PhotoAlbumWidget-0.1.zip (7,96 kb) Unzip to ~/widget/ folder. Requires jQuery library.
First we start with some requirements for the widget we're creating.
The list above is a prioritized backlog and the first version should include items 1 - 4.
We start off with number one, a BlogEngine Widget. To create a widget we add a new folder to the /widget/ folder and we call it PhotoAlbum. Then we create two user controls, one for widget presentation and one for configuration UI. They must be named, by convention, widget.ascx and edit.ascx respectively and should derive from WidgetBase and WidgetEditBase respectively. See more on basic widgetry here by Rtur and here by Mads as well as this, that and whatnot.
That was the easy part.
With the next requirement we first need to get the pictures from somewhere so we skip to the next requirement. Picasa is Google's web album and it has its own REST API as well as a .NET client library. Conveniently there is also a public feed which contains all public photos uploaded to Picasa. (You can of course use your own Picasa album, see the Data API docs for more information). All we need to do is provide a query tag/tags to limit the search or we'll get an error message. The following code retrieves a couple of photos picturing cats:
PicasaService service = new PicasaService("exampleCo-exampleApp-1"); PhotoQuery query = new PhotoQuery("http://picasaweb.google.com/data/feed/api/all"); query.Query = "cat"; query.NumberToRetrieve = 5; PicasaFeed feed = service.Query(query);
foreach (PicasaEntry entry in feed.Entries) { string firstThumbUrl = entry.Media.Thumbnails[0].Attributes["url"] as string; writer.Write("<img src=\"{0}\" alt=\"{1}\" />", firstThumbUrl, entry.Title.Text); }
If we drop the code above into the widget.ascx.cs we affectivally fullfills both requirements 2 and 3 so lets get on with number 4.
Requirement number four implies the Incremental Page Display pattern where the main part of the page is shown quickly and portions of the page that takes longer to load are fetched and displayed asynchronously. To give the user feedback of the loading we place an animated gif image in the widget which is later swapped out when the real pictures arrive. To accomplish this we're using the jQuery JavaScript library which let us get away with very little code for pretty advanced stuff.
First we need to do a little refactoring since the widget needs to do an asynchronous call somewhere to get its content, i.e. the pictures to display. We're gonna go with the simplest possible solution here, just enough to satisfy the requirement. The simplest thing from the widget's point of view is to have the html containing a number of <img> elements returned from the call. Then it's very simple to insert the html into the widget using jQuery. Given that the widget contains a div with the id "photoalbum" this is all it takes:
$("#photoalbum").html(the_html_to_insert);
As it is now, the widget codebehind is rendering the requested html and this is not god. We need to move the code to some place which we can make a http request to and get the html in response. This can be done with a regular aspx page. All we need to do is to put a simple Repeater control on a page and bind it to a list of image URLs which we get from Picasa web album. So, we add a new aspx page to the /widgets/Photo Album/ folder and call it PhotoService.aspx. All we want in response is the <img> tags which should be inserted into the widget so we clear the page from html and put a single Repeater on it like this:
<asp:Repeater ID="pictureRepeater" runat="server"> <ItemTemplate> <asp:Image ID="image" runat="server" ImageUrl="<%# Container.DataItem.ToString() %>" /> </ItemTemplate> </asp:Repeater>
In the codebehind we insert something like before and makes sure we bind to the Repeater control.
// Error checking is omitted for clarity List<string> pictures = new List<string>(); PicasaService service = new PicasaService("exampleCo-testApp-1");
string picasaUri = "http://picasaweb.google.com/data/feed/api/all"; PhotoQuery query = new PhotoQuery(picasaUri); query.Query = "cat"; query.NumberToRetrieve = 6; PicasaFeed feed = service.Query(query);
foreach (PicasaEntry entry in feed.Entries) { string firstThumbUrl = entry.Media.Thumbnails[0] .Attributes["url"] as string; pictures.Add(firstThumbUrl); }
pictureRepeater.DataSource = pictures; pictureRepeater.DataBind();
To test the service we point a web browser to /widgets/Photo Album/PhotoService.aspx which should show a bunch of cats! Everything looks good and all we need to do to get the pictures into the widget are two things. First we need to register the jQuery JavaScript file, either localy or a referer to the jQuery official site. Last we need to add some custom JavaScript that makes the Ajax call and puts the html at the right place.
JavaScript blocks should allways, if possible, be placed as close to the </body> tag as possible. The reason is that the browser won't continue to load the remainder of the page when it hits a JavaScript block but rather wait until it is fully loaded. This is not a problem if we're dealing with short scripts but the jQuery library is relatively large in this context so we need to put it as far down the page as possible. Our own script that does the actual work depends on jQuery, thus it must be loaded last. The problem is that we need to do this in a User control in the middle of the page. To our help to solve this we have the ClientScriptManager that every aspx page has. With the method RegisterStartupScript we get to insert arbitrary scripts just before the </form> tag (which is close enough) of the surrounding page. We make the registrations when the widget is loaded, i.e. in the LoadWidget() method.
With this final step done we have our first version of the Photo Album Widget which is ready for demo.
Before the second iteration I'd like to summarize a couple of things with version one that are not of production quality.
A colleague of mine asked me how to apply a stylesheet to a web page dynamically using jQuery and I had never done such a thing but my first thought was that is must be pretty simple. I've spent a lot of time thinking of so many things other than web et. al. so it was nice to delv into some of that stuff again. Check out the live demo.
As we know stylesheets are defined in the head section of an html file like this
<html> <head> <link rel="stylesheet" href="stylesheet.css" type="text/css" /> </head> <body> ... </html>
Now, say that we want to apply another stylesheet dynamically after the fact, so to speak, triggered by some event. This could be a button click or some other arbitrary event that is triggered. So, what we want to do is simply insert a new <link/> element into the head section of the page DOM. This can be done in a couple of lines of jQuery:
$(document).ready(function() { $("a").click(function() { $('head').append('<link rel="stylesheet" href="style2.css" type="text/css" />'); }); });
The key is at what time we add the link to the style sheet. The first line in the code above repeated here asserts that the DOM is ready for manipulation.
$(document).ready(function() { //... });
The second part repeated here adds a click event to all hyperlinks in the page.
$("a").click(function() { //...
And the very task is performed by the last piece of code where the head element is appended with a new link element.
$('head').append('<link rel="stylesheet" href="style2.css" type="text/css" />');
I've been using Jetbrains ReSharper a while now and I love it. I can't even imagine going back to plain Visual Studio anymore because there are so many things in my daily work that involves ReSharper, even simple tasks like editing source code and navigating through code and source files, let alone creating files and running unit tests.
Now I want to share a user tip I found that isn't obvious to find nor part of any context menu. It's actually a refactoring and I call it Magical strings to variable. You can use it when you end up with multiple equal string literals in a piece of code. You would probably want to gather all of the string literals in a variable and reuse it through out the code. You can use ReSharper to do it for you in a couple of key strokes.
[Test] public void ParentPresenter_Update_should_update_view() { var model = new User { Name = "foo" };
using (mockery.Record()) { Expect.Call(parentView.Username = "foo"); }
using (mockery.Playback()) { IParentPresenter presenter = new ParentPresenter(parentView) { Model = model }; presenter.Update(); Assert.That(presenter.Model.Name, Is.EqualTo("foo")); } }
[Test] public void ParentPresenter_Update_should_update_view() { var name = "foo"; var model = new User { Name = name };
using (mockery.Record()) { Expect.Call(parentView.Username = name); }
using (mockery.Playback()) { IParentPresenter presenter = new ParentPresenter(parentView) {Model = model}; presenter.Update(); Assert.That(presenter.Model.Name, Is.EqualTo(name)); } }
1. Highlight one of the string literals
2. Press Ctrl+R, V (Ctrl+Alt+V)* to introduce a variable
3. Select to replace all occurrences (default option)
4. Pick a name for the variable
..and you're done! Please leave a comment if you find this usefull.
* Visual Studio scheme (ReSharper 2.x / IDEA scheme)
Thanks to the new MetaWebLog API in BlogEngine.NET you can use MS Word 2007 to write your blog posts including using graphics, charts and the full feature set of Word 2007. Read about how you set it up at Rtur.net. You can even use Word 2007 to edit posts on the blog server.
Note: This post was published using Word 2007.