- Posted by liammclennan on November 18, 2009
Dictionary<TKey, TValue> is a generic type that stores collections of KeyValuePair<TKey, TValue>. It is used heavily (actually the IDictionary<TKey, TValue> interface) in Asp.Net Mvc as a parameter to view helper methods.
I am writing this post because I have a tendency to forget the collection initializer syntax for this type of collection, so here it is:
IDictionary<string, int> collection = new Dictionary<string, int>()
{
{ "rows", 7 },
{ "columns", 2}
}
The nice part is that it supports specifying the collection members as anonymous types, instead of having to instantiate new instances of KeyValuePair<TKey, TValue>.
- Posted by liammclennan on October 12, 2009
This is one of those ‘reminder for myself’ type posts. In asp.net mvc a form can be posted (or getted) to a controller action which has a complex type parameter. Asp.net MVC will automatically convert the form values to an instance of the complex type by using the DefaultModelBinder class. Scott Hanselman provides the best documentation of this behaviour.
From time to time I find that I have properties on my action parameter that don’t get bound. Most commonly for me this occurs when the action parameter type as a property called ‘Id’. The reason that ‘Id’ does not get bound is because the MVC template defines a default route with the following patter: {controller}/{action}/{id}. Values that arrive as part of the url get precedence over form values, thus if you have a form value with the same name as a route value the form value will not get bound.
- Posted by liammclennan on September 17, 2009
I continue to be interested in the architecture of the plain, standard, web application. Each of the web application frameworks defines an architecture for the plain web application. Think of Rails and Django (MVC + Active Record), or sharp architecture and Codebetter.Canvas (Asp.net MVC + NHibernate + DDD). This is a starting point from which more advanced and specialised web applications can grow.
Damian Maclennan, or as these guys might say (2:50) 'some guy', presented a simple framework for web applications at Sydney Alt.Net. Damian's example mixes Asp.Net MVC, Fluent NHibernate and Structure Map.
The Good Parts
My favourite part is the way that NHibernate is configured with the IoC container. The author inherits from the Structure Map Registry class and creates a registry called NHibernateRegistry
internal class NHibernateRegistry : Registry
{
public NHibernateRegistry()
{
ForRequestedType<ISessionFactory>()
.CacheBy(InstanceScope.Singleton)
.TheDefault.Is.ConstructedBy(() => new NHibernateSessionFactory().GetSessionFactory());
ForRequestedType<ISession>()
.CacheBy(InstanceScope.Hybrid)
.TheDefault.Is.ConstructedBy(x => x.GetInstance<ISessionFactory>().OpenSession());
}
}
I think this is a neat way to group IoC registrations. The NHibernateRegistry registers NHibernateSessionFactory as a singleton, which is important because NHibernate requires that the session factory is at application scope. The scope for ISession is InstanceScope.Hybrid which means that the scope of an ISession is one HTTP request, exactly what is required for normal NHibernate usage.
The Missing Parts
It is usually desirable to begin a transaction for each ISession and close the transaction prior to the ISession being closed. If the example is extended to include database writes it will fail without transactions. NHProf recommends that transactions be used even for read-only sessions.
Security can be a challenge in Asp.Net MVC. I would like to see how Damian prefers to secure controllers.
The Repository<T> class currently only supports querying by Id. If a more complicated query is required where should it go? The two popular options are: specialised repositories (PostRepository : IRepository<Post>) with query methods and query objects where each query is encapsulated in an object.
Fluent NHibernate is nice but I wonder why auto mapping was not used. It would work nicely for the domain in the example.
Jerry's Final Thoughts
It's good to see the production of this kind of useful guidance. Someone new to the technologies could easily use Damian's example as a starting point for a well designed Asp.Net MVC application. It is certainly a much more helpful starting point than the Visual Studio template.
Until next time, take care of yourselves and each other.
- Posted by liammclennan on July 22, 2009
I spent the weekend in Adelaide for Code Camp SA. Code Camp SA is Adelaide's version of Code Camp Oz in Wagga Wagga, which I also attended and spoke at.
The event was well organised with excellent facilities and catering. Saturday night there was a social dinner at a local pizza restaurant for the tried and true nerd / pizza combination.
I gave my presentation, 8 Reasons Why ASP.NET MVC is better than Webforms on the first day before lunch. To keep things interesting I was followed by Tatham Oddie keeping things balanced with 8 Reasons Why Webforms is better than MVC. His argument was based around the difficulty of creating composite UIs with MVC, which is a valid criticism.
Here is the ASP.NET MVC example code from my talk, including a nifty bulk geocoder for google maps.
- Posted by liammclennan on June 1, 2009
Summary
I think I will begin with the summary so that you don't have to read the rest unless you are curious. The title is approrpriate. This book is not nearly as advanced as Asp.net MVC in Action. It is more suitable for an inexperienced audience. Having said that it is a good, broad introduction to asp.net mvc. If you already completed a project with asp.net mvc you probably already know most of what this book covers. If you are just starting with asp.net mvc then reading this book will introduce you to most of the required concepts far more efficiently than reading dozens of blog posts and msdn articles.
Chapters 1 & 2
The book begins with a simplified treatment of the MVC pattern. It is the usual content that unfortunately doesn't deal with why a person would want to use the MVC pattern. The author nicely explains why a person would want to use ASP.NET MVC by talking about the design goals of the framework.
The comparison of MVC to webforms is actually pretty good. I could not detect the usual bias one way or the other.
Chapter 3 Handling Interactions
Chapter 3 covers the basic interactions between controllers and views. A sidebar in this chapter introduces the Model-View-ViewModel concept.
Chapter 4 Components in the MVC framework
This chapter is a walk-through of the request lifecycle, including the extensibility options. It also includes information about models, views and controllers.
Chapter 5 Routing
Covers the basics of routing. How urls are mapped to actions, how to generate urls and how to constrain routes values.
Chapter 6 Customizing & Extending the ASP.NET MVC Framework
The action filter example is the ultimate AOP cliche - logging. The coverage of custom action results and custom views is informative.
Chapter 7 Using Existing ASP.NET Features
This chapter is a recap of ASP.NET features. TempData is also explained.
Chapter 8 AJAX and ASP.NET MVC
The javascript style is not good (obtrusive procedural javascript) but perhaps that is acceptable since this is not a book about javascript. I love the coverage of using jQuery with JsonResult. This is one of my favourite techniques when using ASP.NET MVC.
Chapter 9 Testing
Until I reached chapter nine I thought testing had been neglected, but in fact it gets a whole chapter! Again complete coverage would require a book of its own so the author makes a valiant attempt to cover this issue in a chapter. Mocking is demonstrated with the Moq framework which is impressive, although I don't think it fits very well with the rest of the book which seems to be aimed at beginners.
Chapter 10 Hosting & Deployment
Chapter 10 covers the less glamorous, but still important, topic of deployment. The discussion of classic and integrated modes in IIS 7 is interesting. The troublesome issue of Asp.Net MVC on IIS 6 is dealt with sufficiently.
The book ends with a number of appendixes, including one that describes cartrackr, the author's example asp.net mvc application.
- Posted by liammclennan on May 28, 2009
The good people at Telerik have been kind enough to integrate their UI controls with the ASP.NET MVC framework so that we don't have to go without glorious and essential features like spell checking and paste-from-word. Their website does provide guidance for doing this, however I found that their instructions don't quite work so I will post my own. These instructions cover the text editor but the other controls should be similar. I won't go though everything, just the bits that Telerik left out, so make sure you read the official documentation.
Install the Telerik RAD controls
That name bugs me. They might as well have called it the 'like-cowabunga-narly-rad-fully-awesome-mega-xp-titanium-control-suite'. If, like me, you don't fancy running a 300M installer you can instead download a zip and manually copy the files you need. I recommend this approach since it terns out you only need one file.
Add a Reference to Telerik.Web.UI.dll
All that is required is to add a reference from your MVC project to the Telerik.Web.UI.dll. Here is the first place where the telerik documentation let me down. They say to reference the dll in the bin directory but if you are using .NET 3.5 then you need to reference the dll in the bin35 directory.
Add some things to Web.config
Read the instructions and add the required handlers to web.config. If you want the editors dialog boxes to work then you must also add a http handler for that. The changes to the web.config are:
<httpHandlers>
...
<add path="Telerik.Web.UI.WebResource.axd" type="Telerik.Web.UI.WebResource" verb="*" validate="false" />
<add path="Telerik.Web.UI.DialogHandler.axd" verb="*" type="Telerik.Web.UI.DialogHandler" validate="false" />
</httpHandlers>
<handlers>
...
<add name="Telerik_Web_UI_WebResource_axd" verb="*" preCondition="integratedMode" path="Telerik.Web.UI.WebResource.axd" type="Telerik.Web.UI.WebResource" />
<add name="Telerik_Web_UI_DialogHandler_axd" verb="*" preCondition="integratedMode" path="Telerik.Web.UI.DialogHandler.axd" type="Telerik.Web.UI.DialogHandler" />
</handlers>
If you add the editor control to an mvc partial then you must include the rad stylesheet manager and rad script manager in the partial. You must also include the rad script manager in the view that includes the partial. Weird I know. Here is an example of what the partial might look like:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
<telerik:RadScriptManager ID="scriptmanager2" runat="server"></telerik:RadScriptManager>
<%
editor.Content = Model.Content;
%>
<telerik:RadStyleSheetManager ID="stylesheetmanager" runat="server" ></telerik:RadStyleSheetManager>
<telerik:RadEditor runat="server" ID="editor" DialogHandlerUrl="~/Telerik.Web.UI.DialogHandler.axd" />
</div>
Conclusion
I was impressed that Telerik have any MVC support at all, and only slightly disappointed that their instructions left a few things out. I usually find the RAD suite too heavy weight. In the past adding it to a project has added something like 10,000 files. However, in this case I have been able to add the editor control to an application in a clean and lightweight manner. Telerik win because it is a good editor and it has a trial version, unlike Tiny MCE which has no trial for the image upload functionality is not guaranteed to work with MVC.
- Posted by liammclennan on May 19, 2009
Gravatar is a service that provides globally unique avatars linked to email addresses. Imagine you could include a user's gravatar in a view simply by passing their email address to a helper:
<img src="<%= Url.Gravatar("user@domain.com") %>" />
All we need to do is to add some extension methods to UrlHelper to generate the url to the gravatar service:
public static class UrlExtensions
{
public static string Gravatar(this UrlHelper url, string emailAddress)
{
var baseUrl = "http://www.gravatar.com/avatar/{0}";
return String.Format(baseUrl, MD5Hash(emailAddress.ToLower()));
}
public static string Gravatar(this UrlHelper url, string emailAddress, int size)
{
var baseUrl = "http://www.gravatar.com/avatar/{0}?s={1}";
return String.Format(baseUrl, MD5Hash(emailAddress.ToLower()), size);
}
private static string MD5Hash(string input)
{
StringBuilder hash = new StringBuilder();
MD5CryptoServiceProvider md5provider = new MD5CryptoServiceProvider();
byte[] bytes = md5provider.ComputeHash(new UTF8Encoding().GetBytes(input));
for (int i = 0; i < bytes.Length; i++)
{
hash.Append(bytes[i].ToString("x2"));
}
return hash.ToString();
}
}
The second overload of the Gravatar() method accepts a parameter called 'size' that is the desired size of the gravatar in pixels. The default is 80.
- Posted by liammclennan on May 2, 2009
The default Asp.Net MVC View Helpers use method overloads to allow customisation of the generated output. Here is an example:
<%= Html.TextBox("Chapter_Slug", Model.Chapter.Slug, new { @class="required", title="Slug"}) %>
I have never been particularly happy with the conflicting method overloads and the use of the anonymous object to set attributes. Using MVCContrib you can use a fluent interface instead. The equivalent with fluent helpers is:
<%= this.TextBox(m => m.Chapter.Slug).Class("required").Title("Slug") %>
To use the MVC Contrib Fluent HTML Helpers:
- Get MVC Contrib and add a reference to MvcContrib.FluentHtml.dll.
- Inherit views from MvcContrib.FluentHtml.ModelViewPage<Model> and MvcContrib.FluentHtml.ModelViewUserControl<Model> instead of System.Web.Mvc.ViewPage<Model> and System.Web.Mvc.ViewUserControl<Model>.
- Use the fluent helpers on the view base classes instead of the HtmlHelper extension methods.
- Posted by liammclennan on April 24, 2009
Critics of ASP.NET MVC often point out that view code can end up looking a bit like classic ASP spaghetti code. Two of the major offenders are conditionals and loops in the view. Consider the following view code:
<script type="text/javascript">
jQuery(document).ready(function() {
<% if (Model.ShouldJumpToSection)
{ %>
Chapter.JumpToAnchor('<%= Model.Section.Slug %>');
<%
}
%>
});
</script>
It is difficult to read. A good strategy to clean up views is to try to move conditionals and loops to the controller or to helper methods. Rob Conery has tackled this on his blog. For situations like the above I like to use a helper extension method to move the conditional to a helper. The code is then simplified to:
<script type="text/javascript">
jQuery(document).ready(function() {
<% Html.WriteIf(Model.ShouldJumpToSection, "Chapter.JumpToAnchor('" + Model.Section.Slug + "');"); %>
});
</script>
You can see that it is much easier to read. Because this code is not using the <%= %> notation you have to remember to add a ; at the end of the line. An important thing to keep in mind is that the method paramters are evaluated before the method is called, meaning that they are evaluated even if the conditional is false. Here is the code for the helper methods that I use:
public static class HtmlExtensions
{
public static void WriteIf(this HtmlHelper helper, bool condition, string truePart, string falsePart)
{
helper.ViewContext.HttpContext.Response.Write(condition ? truePart : falsePart);
}
public static void WriteIf(this HtmlHelper helper, bool condition, string truePart)
{
WriteIf(helper, condition, truePart, string.Empty);
}
}
Another common pattern that I see in MVC views is:
<% if (ViewData.Model.Count == 0) { %>
Nothing to display
<% } else {
foreach (var item in ViewData.Model) { %>
...render the item here...
<% }
} %>
It is not too bad but it can be cleaned up a lot by moving the conditional to the controller and placing the body of the loop in an MVC View User Control. In the controller check if the collection is empty and if so render a special empty view. Then the view above can be simplified to:
<% foreach (var item in ViewData.Model) {
Html.RenderPartial("_Item", item);
} %>
No spaghetti here.
- Posted by liammclennan on April 24, 2009
Some time ago I wrote about optimising javascript and css file inclusion during the build process. This is necessary because our natural tendancy as developers, to neatly split these file into small modules with plenty of whitespace and commenting, result in unacceptable performance. It turns out that loading many small js files in a page has terrible performance characteristics and whitespace and commenting can slow things down considerably. I consider the technique described a success because the output was good from the performance point-of-view. Unfortunately, the developer experience was poor. There were a lot of steps required and it was easy to make a mistake and introduce a difference between the development environment and the production environment, which is high on my not-to-do list.
I am working on a new project and at the point where I need to think about optimising css and javascript again. This time I have gone with a slightly less optimal, but much simpler approach, based on conventions and adding extension methods to the UrlHelper class (this is part of Asp.Net MVC). Here is how it works.
In my web project I have the standard Content folder for storing resources. With Content I have created Scripts for javascript files and CSS for CSS files. Within Scripts and CSS I have created min folders, which will store the minified versions of the resources. The convention is that every js or css resource has a minified equivalent with the same name in the /min directory. The minified versions will be produced automatically during the build process.

During development I don't want to use minified files. I like to use Firefox to inspect js and css and minification makes this impossible. To make the loading of resources (js and css) choose between full and minified versions transparently I have implemented helper methods on the UrlHelper class. The methods are Script(...) and CSS(...).
public static class UrlExtensions
{
/// <summary>Returns the url for a javascript file. In production the files come from the min sub-directory.</summary>
public static string Script(this UrlHelper url, string filename)
{
return ResolveUrlForEnvironment(url, "~/Scripts/", filename);
}
public static string CSS(this UrlHelper url, string filename)
{
return ResolveUrlForEnvironment(url, "~/Content/CSS/", filename);
}
private static string ResolveUrlForEnvironment(UrlHelper url, string path, string filename)
{
if (!IsProduction()) return url.Content(path + filename);
return url.Content(path + "min/" + filename);
}
private static bool IsProduction()
{
return (HttpContext.Current != null && !HttpContext.Current.IsDebuggingEnabled);
}
}
At runtime the application determines if it is in a 'production' environment by checking the IsDebuggingEnabled property. This corresponds to the debug attribute on the compilation element in web.config. If it is production then the helpers return the paths to the minified files, otherwise the path to the full files is returned. These helpers are used like this:
<link href="<%= Url.CSS("Site.css") %>" rel="stylesheet" type="text/css" />
<script src="<%= Url.Script("jquery-1.3.2.js") %>" type="text/javascript"></script>
To make this strategy work the build process has to: set the debug="true" attribute in web.config, and produce the minified js and css files. The minification can be done with packer and js min as described in my previous post. Changing the web.config can be done using NAnt or MSBuild.
To tackle the problem of many http requests to fetch js and css I plan to use the lo-fi approach of limiting the number of files. I will try to group my css and javascript so that there is roughly one file of each type loaded per page loaded in my application. This means that I will have many javascript 'classes' per javascript file. It is not ideal but it is simple and performant.
Overall I am much happier with my new approach. It is an acceptable compromise that gives me a much simpler model to work with, and I think that simplicity is something that we do not value high enough.