@model and beyond | Peter van Ooijen


In my previous post I had been fiddling with the html helper used in Razor views. Since then our custom html-extensions have been doing great things for our project. To mention some:

  1. Standardizing the look and feel. It is far more consistent and maintainable to set attributes (including a css class) and event handlers in one centralized place.
  2. Simplify the script. Often a part of the logic the script will follow is already known server side. Instead of writing everything out in javascript rendering the intended statements leads to a leaner client. There is an example in my previous post on building post-data.
  3. Decoupling the libraries used. At the moment we are using the Telerik MVC suite. In my previous post I described how our html helpers build standardized Telerik components for our views. In the not to far future we want to switch to the Telerik Kendo suite. Having wrapped up the library dependency in our Html helper will make this switch a lot easier to implement.

What has evolved is the way we work with the model. In MVC the implementation of the controller and the view is clear. When it comes to the implementation of the model there are almost as many different styles of implementation as there are programmers. In general the model can bring any data to the view you can imagine. Not only the source of the data varies, from plain sql to a C# property, also the use of the model’s data varies. It can be a customers name from the database. Or it can be the string representation of some html attribute needed for a fancy picker. Here data and presentation start to get mixed up. Our extensions needed information for the Html-Id. The original Html helper had a custom constructor to get that specific data from the model into the helper. Which required to create our own htmlhelper when starting the view and use that one instead of the standard @html. As seen in the eposHtml in the previous story. It would be cleaner if our extension methods could be satisfied with the default html helper. It would also be cleaner to keep a better separation between ‘real’ data and presentation.

The model is available in every HtmlHelper extension method.

public static PostDataBuilder<TModel> PostData<TModel>(this HtmlHelper<TModel> htmlHelper)


    return new PostDataBuilder<TModel>(Id(htmlHelper.ViewData.Model));



It’s a property of the ViewData.

In our case we needed something to give the control an unique Id. The Id method builds that Id. Previously we passed the Id-base in the constructor, which lead to the custom helper. A far more elegant solution is using a very basic IOC-DI pattern. As implemented By the Id method

private static string Id(object model)


    var complex = model as IProvideCompositeId;

    if (complex != null)

        return complex.CompositeId;

    var simple = model as IProvideId;

    return simple == null ? “” :  simple.Id < 0  ? String.Format(“N{0}”, Math.Abs(simple.Id)) : simple.Id.ToString();



The method queries the model first for the IProvideCompositeId interface, in case the model does not implement that it is queried for the IprovideId interface. Resulting in a string which can be safely used in an HtmlId. (A negative number would lead to a ‘–’ in the string, which is not accepted in an Html Id).

These interfaces are very straightforward

public interface IProvideCompositeId


    string CompositeId { get; }



public interface IProvideId


    int Id { get; }



In case the model is going to be used in a view requiring unique Id’s the model has to implement one of these interfaces.

public class FactuurDefinitie : IProvideCompositeId


    public readonly int IdTraject;

    public readonly int UZOVI;

    public readonly bool Verzekerd;


    public FactuurDefinitie(int idTraject, int uzovi, bool verzekerd)


        // The usual stuff



    public string CompositeId


        get { return String.Format(“{0}{1}{2}”, IdTraject, UZOVI, Verzekerd); }




Working this way:

  • We can use our custom html extensions in the default html helper
  • Specific data from the model is available inside our extensions
  • The model and the view do not get entangled

The code is no big deal. I know. But the model is something whose horizons are still not in sight.