The right amount of separation of concerns in Umbraco Razor?

We hear it’s a good thing to separate view code from logic, and also to separate code into controller, model and view files. What does that actually mean? And why is that a good thing? Also does this mean we need to create model and controller class files for all our Umbraco Razor scripts?

Consider a plain read-only, HTML rendering razor script with a good amount of HTML, over a page long. Nothing unusual and it works perfectly fine as it is:

The code in this post is for Umbraco MVC (4.10+), but it’s concepts apply to all versions of Umbraco.

<...lots of tags above this point...>
<div class="widget">
    <h4>Recent Posts</h4>
    <ul>
        @foreach (var blogPost in Umbraco.TypedContent(1068)
            .Children().Where(t=>t.IsVisible()).OrderByDescending(t => t.CreateDate).Take(10))
        {
            <li><a href="@blogPost.Url">@blogPost.Name</a>
            @foreach (var item in blogPost.GetPropertyValue<string>("categories").Split(','))
                { <span>@item</span> } </li>
        }

    </ul>
</div>
<...lots of tags beneath this point...>

A few things that can be made better here as I see it:
– The recent blog posts widget can be separated from the rest of the view into a reusable partial.
– Intentions are not clear, what exactly are we trying to do with the chained methods?
– Hard coded node number 1068, what if we change that one later?
– Lot of C# mixed inside HTML makes both the HTML and the C# harder to read and problems harder to find.

I suggest:
– Separate the code into a partial / separate razor script, give it a name and or a location that both describes the type of HTML it renders aswell as the content, for example “Widgets/RecentBlogPosts.cshtml”.
– Move all C# code, but a bare minimum to the beginning of the script.
– Specify the intent with the code being used by using good names, close to what it is described as on the actual site, or in the specification to the customer.
– Stay away from hard coded node numbers.
– Use C# Linq with Lambdas together with typed content. It’s a great syntax to express Umbraco content queries.
– Use the .Select method, together with anonymous object to return exactly what you need, i.e. arrays and objects with only simple types. This will help you make clear what you need and will show you possible problems early.

Main cshtml:

<...lots of tags above this point...>
@Html.Partial("Widgets/RecentBlogPosts")
<...lots of tags beneath this point...>

Partials/Widgets/RecentBlogPosts.cshtml:

@{
  var blogPostsRootNode = Model.Content.AncestorOrSelf(1);
  var recentBlogPosts = blogPostsRootNode.Children
    .Where(t=>t.IsVisible())
    .OrderByDescending(t => t.CreateDate)
    .Take(10)
    .Select(p => new
    {
      p.Url, 
      p.Name, 
      Categories = 
        (p.GetPropertyValue<string>("categories") ?? "")
          .Split(',')
    });
}
<div class="widget">
    <h4>Recent Posts</h4>
    <ul>
        @foreach (var blogPost in recentBlogPosts)
        {                                                            
            <li><a href="@blogPost.Url">@blogPost.Name</a>
            @foreach (var category in blogPost.Categories)
            { <span>@category</span> } </li>
        }
    </ul>
</div>

What about separate model, view and controller classes?
The C# part of the script is building a ViewModel and, as such, could be placed in a C# model file, which in turn could be instantiated from the controller file firing up the view file.

We certainly could. And we could create a strongly typed view, and unit test the controller and the model. But would it really help us for this kinds of scripts that only show content – and does not deal with posted data?

I don’t think so. I found the approach described in this blog post be good amount of separation of concerns for views like this, I would very much like to hear experiences / opinions / examples from you, dear reader!

Happy coding

Advertisements

11 thoughts on “The right amount of separation of concerns in Umbraco Razor?

  1. Great post Jonas!

    It’s still early days for MVC in Umbraco so great to see someone playing with some pragmatic best practises, and even better to see they are exactly how I’m working 🙂

    You are right that we could go the whole hog and move all logic into controllers etc, but I like yourself, find the simpler approach works just as well for 99% of sites, offering good separation and logic to the file structure, it’s a big thumbs up from me.

    Matt

  2. I someone who is a hardcore XSLT fan, it’s good to see this stuff 🙂 I’m learning Razor at the moment, and currently using a ‘code like hell’ fast rough approach, it’s messy and dirty, but hopefully soon I’ll be able to find this beauty!

  3. […] good posts on good practices and how to retain separation of concerns using MVC in Umbraco (see http://joeriks.com/2013/05/22/the-right-amount-of-separation-of-concerns-in-umbraco-razor/ and http://ndesoft.dk/2013/05/25/how-to-create-a-real-mvc-app-using-umbraco/)  Here’s my […]

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s