Polymorph Razor Views

As an object-orientation-spoiled programmer, when you come to use an HTML rendering engine such as Razor you will soon start to wish for the same couple of design advantages that object orientation brings along.

Using polymorphism in “class-ic” object orientation, e.g., you can do things like that (simplified code snippet – don’t try copy-paste):

class Person
{
    string FirstName { get; set; }
    string LastName { get; set; }
    virtual string FormatName()
    {
        return FirstName + " " + LastName;
    }
}

class PersonWithMiddleName : Person
{
    string MiddleName { get; set; }
    override string FormatName()
    {
        return FirstName + " " + MiddleName + " " + LastName;
    }
}

That means, you can write some generic code that iterates over a couple of Person objects and prints their names without caring how they are actually built. By default a Person would yield their first and last name when invoking FormatName, but if you need to print a middle name, too, you can simply subclass Person and override FormatName. When invoking FormatName on an instance of PersonWithMiddleName, even when it is known as Person only, it will apply the most special implementation found, here the one including the middle name.

The good news – you can get that in Razor, too

Razor has a concept that reminds me of the same type of polymorphism. Using Display Templates and Editor Templates you can define a general template to render a Person:

@* ~/EditorTemplates/Person.cshtml *@
@model Person
<div class="Person">@Model.FirstName @Model.LastName</div>

This template applies each time you use EditorFor with a Person type property:

@* suppose a class Book { Person Author { get; set; } *@
@model Book
@Html.EditorFor(m => m.Author)

Now say we have a book with a PersonWithMiddleName author. Then the Person template is still applied, because PersonWithMiddleName inherits from Person. But we have the option to override the template for the special class:

@* ~/EditorTemplates/PersonWithMiddleName.cshtml *@
@model PersonWithMiddleName
<div class="Person">
@Model.FirstName @Model.MiddleName @Model.LastName
</div>

Now, whenever the book has a PersonWithMiddleName author, this template applies. For all other Person objects, the Person.cshtml applies.

We can take it a step further! “Base templates”

If you did not know of Editor Templates before, you might be so excited about them now that you want to try them out right away and cannot think clearly enough to head on reading. Just return later.

If you already did know Editor Templates you might have been wondering: Can we take it a step further? In C# the overriding method can call its base method to reuse the code of the base class:

class PersonWithMiddleName : Person
{
    string MiddleName { get; set; }
    override string FormatName()
    {
        return base.FormatName() + ", middle name: " + MiddleName;
    }
}

Can we do that with Editor Templates?

We can, making use of this helpful answer on stackoverflow.

@* ~/EditorTemplates/PersonWithMiddleName.cshtml *@
@Html.Partial("~/EditorTemplates/Person.cshtml", Model)
, middle name:
@MiddleName

At a first glance you might think it looks a bit clerky but it is not: Just as a subclass needs to reference its base class with its full class name including the namespace, we reference the “base template” using its full path. We simply pass that template the same model. Thus it also uses the exact same ViewData (e.g. the “HtmlFieldPrefix”). Thus we pass it the context, which is kind of analaguous to the “this” keyword in C#.

Template Method Pattern

Now we get to an even more interesting point: If we have inheritance and polymorphism at hand, can we use any of the popular object oriented design patterns?

I tried the template method pattern. It is very useful in this place because when you render a view it is pretty likely that you want to “inject” some additional HTML in the midst of the rendering output of the base template.

Taking the example from above, let us say we want to render FirstName + MiddleName + LastName again:

@* ~/EditorTemplates/Person.cshtml *@
@model Person
@{
    var extension1 = ViewData.ContainsKey("ExtensionPoint1")
        ? ViewData["ExtensionPoint1"] : string.Empty;
}
<div class="Person">
    @FirstName
    @Html.Raw(extension1)
    @LastName
</div>

The template basically renders FirstName + LastName but provides an “extension point” for inserting HTML between the two names. A pretty silly application of the pattern, but, you know, it is an example only.

The extension must be a string containing HTML. It is only rendered if you provide it.

@* ~/EditorTemplates/PersonWithMiddleName.cshtml *@
@model PersonWithMiddleName

@{
    var extension1 = @RenderMiddleName().ToString();
    ViewData["ExtensionPoint1"] = extension1;
}
@Html.Partial("~/EditorTemplates/Person.cshtml", Model)

@helper RenderMiddleName()
{
    @MiddleName
}

Our specialized template makes use of the Person.cshtml “base template” for rendering the parts that the base template already knows best how to render. But it combines that with its own specializd rendering by only injecting the part that is really different from the base template – the middle name.

We don’t define the extension1 string directly but use a Razor helper instead. This allows us to make use of the Razor syntax to define the part to inject rather than writing lenghy worms of plain HTML strings.

Conclusion

Using Editor Templates (and Display Templates) in a smart combination with Html.Partial and ViewData you can leverage a (maybe) unknown range of object-oriented techniques for building your web pages, allowing for a modular, clean design in this part of your web application just like in the rest of your application, thus improving code reuse and maintainability of your templates.

I think this is great news! What do you think? Have you been using this approach before? Do you have better ideas? Or do you see any issues with this approach?

Do not fix code duplication*

(* Full title: – Do not fix code duplication – solve it)

When you find two identical or near-identical pieces of code in your codebase this is identified as code duplication. There are many resources to learn why code duplication is an issue.

When you find duplicate code, the intuitive reaction is to fix it right away. Don’t. Here is why:

There is a subtle difference between fixing an issue and solving it. Fixing means to remove it. Solving means to analyze the root cause and fix that. When you fix code duplication the typical thought process is: “Oh, here is a piece of code, and here is the same again. That’s bad. Let us merge them. Hm, maybe we can extract a new private method. Or we create a class for it. Or we place it in this class here, since this is already used in both places anyway. Oh yes, let’s do that.”

However, when you find duplicate pieces of code this is usually not the root issue. It is only a smell. There might be a flaw in your design. The place of your code might be discrepant from where the associated semantic concept belongs to.

Take this example:

We have a model class that represents a service product in three shapes: Basic, Medium, Top. We find this in a property:

class Product
{
    int ProductType { get; set; }
}

Then we have a document generation module for printing contracts or offers. Therein we find multiple blocks of the form

if (product.ProductType == Constants.MEDIUM
    || product.ProductType == Constants.TOP)
{
    ...
}

We could fix that by extracting a local variable:

var isMediumOrTop = product.ProductType == Constants.MEDIUM
                    || product.ProductType == Constants.TOP;

Or we could extract a method

private static bool IsMediumOrTop(product) {...}

No, much better. Let us introduce a helper class.

public class AllPurposeDocumentGenerationHelper { ... }

We won’t do that.

Instead we lean back and think:

  • We have duplicate code. Why is that?
  • Is there a business meaning attached to this condition?
  • What is it?

We find that actually the business wants to “unlock” a certain special offer in the product if you buy the medium version or above. So it is a business thing. It is nothing specific to generating a document, nor is “IsMediumOrTop” necessarily a good name to represent it.

Recognizing that, we decide that the model needs to be extended:

bool SpecialOfferIncluded
{
    get
    {
        return ProductType == Constants.MEDIUM
               || ProductType == Constants.TOP;
    }
}

The conditionals in the document generation will now look like this:

if (product.SpecialOfferIncluded) { ... }

The semantic meaning will be immediately clear to the reader (and coder). Also, by looking at the new model property you will learn a business rule: “If the product type is medium or top, the special offer is unlocked.”

Next we notice that in our front end code we have the same conditional but there it was not so obvious:

if (product.ProductType == Constants.BASIC) { ... }

Gotcha!

if (!product.SpecialOfferIncluded) { ... }

No, wait! We wanted to lean back and think first. While doing that, it might turn out that this piece of code is actually not related to the special offer thing. Instead it is really specific to the product type. Luckily we now have a way to make a semantic distinction between the two meanings.

Soon the business will come to you and tell you that in the next version, the SpecialOffer should be included only if the price exceeds a certain limit. Easy:

bool SpecialOfferIncluded
{
    get
    {
        return Price > Constants.MIN_PRICE_FOR_SPECIAL_OFFER;
    }
}

Done.

Conclusion

When you face duplicate code, take it as a opportunity to think about your design, the business, and how well the design represents the semantics of your application. There are good chances you will find a way to improve that, thus having really solved the root issue of the duplicate code rather than just having it fixed in an arbitrary way.