Sunday, 23 August 2015

Code As Data With Reflection

Other than occasional use, working with reflection using C# isn't something I've had that much need to do. Recently though I was working on an additional feature for the Umbraco package The Dashboard. It provides a nice first screen for editors, showing their recent edits and other work carried out on the site content.

The idea for the new feature was to create a developer version of this, that displayed various details about the code that had been implemented on the project. The use case being in the case of inheriting or coming back to a site, being able to have a quick overview of the techniques that have been used for route hijacking, surface controllers, application events and the like.

In order to implement this it was going to be necessary to make quite heavy use of reflection and this post highlights a few of the methods used.

Getting instances of types

In the case of Umbraco route hijacking using custom controllers it's necessary to implement an MVC controller that implements an interface (IRenderMvcController). Similarly for surface controllers, you need to inherit from a base class (SurfaceController). So to find all the instances of these I needed to search all the assemblies of the project and find all non-abstract, classes that implemented a given interface or inherited a given base type. I also wanted to exclude anything that came with the Umbraco core itself as that wasn't useful to display.

Here's the code I used:

public class ControllerDetailDto
{
    public string Name { get; set; }

    public string Namespace { get; set; }
}

public IEnumerable<ControllerDetailDto> GetControllersAssignableFrom(Type baseType)
{
    return GetNonCoreTypesAssignableFrom(baseType)
        .Select(x => new ControllerDetailDto
        {
            Name = x.Name,
            Namespace = x.Namespace,
        });
}

private IEnumerable<Type> GetNonCoreTypesAssignableFrom(Type baseType)
{
    return AppDomain.CurrentDomain.GetAssemblies()
        .SelectMany(s => s.GetTypes())
        .Where(p => baseType.IsAssignableFrom(p) && p.IsClass && !p.IsAbstract && !p.Namespace.ToLower().StartsWith("umbraco."));
}

Getting method details

In the case of custom controllers used for route hijacking, I also wanted to get the list of action methods. This was done by finding all public, non-static methods direct declared on the controller and filtering by those that returned ActionResult or something inheriting from it. I was only interested in the GET ones so obtained all those by excluding any that had an [HttpPost] attribute.

The crucial part of the code for doing this was as follows:

public IEnumerable<string> GetActionMethodsOnController(Type controllerType)
{
    return controllerType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
        .Where(x => typeof (ActionResult).IsAssignableFrom(x.ReturnType) &&
            !x.Name.StartsWith("get_") &&
            (!x.GetCustomAttributes(typeof (HttpPostAttribute), false).Any()))
        .Select(x => x.Name)
        .OrderBy(x => x);
}

Getting event details

The last task I had was to get details of the application event handlers that had been registered. For a given Umbraco service, e.g. ContentService, there are a number of methods that may have handlers registered on it - to carry out actions on Saving of content for example.

This wasn't particularly straightforward but I got some help from this blog post by David Kowalski and a chapter he referenced from C# in Depth. The code I used to get this information was as follows:

public class ReflectedClassDto
{
    public string Name { get; set; }

    public string Namespace { get; set; }
}

public class CustomEventDto
{
    public string EventName { get; set; }

    public IEnumerable<ReflectedClassDto> Handlers { get; set; }
}

public IEnumerable<CustomEventDto> GetCustomEvents(IService serviceInstance)
{
    return serviceInstance.GetType().GetEvents()
        .Select(x => new CustomEventDto
        {
            EventName = x.Name,
            Handlers = GetCustomEventHandlers(serviceInstance, x)
        })
        .Where(x => x.Handlers != null && x.Handlers.Any());
}

private static IEnumerable GetCustomEventHandlers(IService serviceInstance, EventInfo eventInfo)
{
    var fi = GetEventField(serviceInstance, eventInfo);
    if (fi != null)
    {
        var del = fi.GetValue(serviceInstance) as Delegate;
        if (del != null)
        {
            return del.GetInvocationList()
                .Where(x => !x.Method.DeclaringType.FullName.ToLower().StartsWith("umbraco."))
                .Select(x => new ReflectedClassDto
                {
                    Name = x.Method.Name,
                    Namespace = x.Method.DeclaringType.FullName,
                });
        }
    }

    return null;
}

private static FieldInfo GetEventField(IService serviceInstance, EventInfo eventInfo)
{
    return serviceInstance.GetType()
        .GetField(eventInfo.Name,
            BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public |
            BindingFlags.FlattenHierarchy);
}

The first step is to get the list of events defined on the service instance - these are things like OnSaving etc - that have at least one handler defined. To get the event handlers we then extract the private field that backs the event and obtain the value of that field as a delegate (of type MulticastDelegate). With that there's a method called GetInvocationList() that allows you to retrieve all the defined handlers for the event. Again I remove all the ones that come with the Umbraco Core.

To see this in context see the open-source repository for the package and specifically this file.

Friday, 7 August 2015

(Yet) Another Look at Unit Testing Umbraco Surface Controllers

A quick recap

A little while back now I spent a bit of time investigating how one might go about unit testing Umbraco surface controllers. With the help of information posted by some others that had similarly looked into it I found there was a method that worked, but it wasn't ideal for a number of reasons.

Firstly there was a need to utilise an Umbraco test helpers dll, that contained implementations of various base classes that could be used to support testing. No great hardship to use that but it did mean you had to compile the source to get it and it led to some other restrictions on your tests.

One of those being you had to use NUnit. Again, a perfectly decent test runner but if you generally used MSTest or something else you had to make a switch.

And lastly in order to create various surface controller dependencies, you had to use some rather impenetrable looking reflection code to get around the fact that certain classes and methods were marked as internal rather than public. This worked, and only needed to be written once in a a base class to utilise it in all your tests, but was rather brittle. Code marked as internal is done so for a reason, one of those being that even if it's potentially useful to provide public access to developers, the core team haven't yet committed to the implementation so reserve the right to change it, even in a minor upgrade.

Putting all that together probably explains that although I did have a method that worked it wasn't something I made part of my general work with Umbraco.

The situation today

One thing I've been following and looking forward to the release of version 7.3 of Umbraco is the discussion on improved testing support. And given the recent release of this in beta, wanted to check it out.

Am pleased to report things are a lot easier now. There's still a bit of set-up and mocking code required, but that's unavoidable to ensure the surface controller has access to things like the Umbraco context in it's operations. But there are no base classes that you are required to depend on, no tie to a particular unit testing framework and no longer a requirement for reflection code.

As well as what follows, you can see some more examples of this in the Umbraco source code itself - which I used for reference. You can also take a look through the code of the Umbraco REST API which as noted in the comments below also contains several examples.

An example

I'll go back to the simple example I was looking to test in the previous blog post:

[HttpPost]
public ActionResult CreateComment(CommentViewModel model)
{
    if (!ModelState.IsValid)
    {
        return CurrentUmbracoPage();
    }

    TempData.Add("CustomMessage", "Thanks for your comment.");

    return RedirectToCurrentUmbracoPage();
}

And I have these two tests:

[TestMethod]
public void CreateComment_WithValidComment_RedirectsWithMessage()
{
    // Arrange
    var controller = GetController();
    var model = new CommentViewModel
    {
        Name = "Fred",
        Email = "fred@freddie.com",
        Comment = "Can I test this?",
    };

    // Act
    var result = controller.CreateComment(model);

    // Assert
    var redirectToUmbracoPageResult = result as RedirectToUmbracoPageResult;
    Assert.IsNotNull(redirectToUmbracoPageResult);
    Assert.AreEqual(1000, redirectToUmbracoPageResult.PublishedContent.Id);
    Assert.IsNotNull(controller.TempData["CustomMessage"]);
}

[TestMethod]
public void CreateComment_WithInValidComment_RedisplaysForm()
{
    // Arrange
    var controller = GetController();
    var model = new CommentViewModel
    {
        Name = "Fred",
        Email = string.Empty,
        Comment = "Can I test this?",
    };
    controller.ModelState.AddModelError("Email", "Email is required.");

    // Act
    var result = controller.CreateComment(model);

    // Assert
    var umbracoPageResult = result as UmbracoPageResult;
    Assert.IsNotNull(umbracoPageResult);
    Assert.IsNull(controller.TempData["CustomMessage"]);
}

To support testing there's a need to make a minor amend to the controller itself, to create a constructor that allows the passing of an instance (mocked for testing) of the Umbraco context and helper:

public class BlogPostSurfaceController : Umbraco.Web.Mvc.SurfaceController
{
    private readonly UmbracoHelper _umbracoHelper;

    public BlogPostSurfaceController(UmbracoContext umbracoContext)
        : base(umbracoContext)
    {
    }

    public BlogPostSurfaceController(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper)
        : base(umbracoContext)
    {
        _umbracoHelper = umbracoHelper;
    }

    public override UmbracoHelper Umbraco
    {
        get { return _umbracoHelper ?? base.Umbraco; }
    }
}

And then in the test project I need to implement the helper method I've created above called GetController(). I've placed all this code in my test class but in practice it would make sense to move much of this into your own test base class, so it can be reused across tests.

private BlogPostSurfaceController GetController()
{
    var appCtx = MockApplicationContext();
    var umbCtx = MockUmbracoContext(appCtx);

    var controller = new BlogPostSurfaceController(umbCtx, new UmbracoHelper(umbCtx));
    SetupControllerContext(umbCtx, controller);

    return controller;
}

private static ApplicationContext MockApplicationContext()
{
    return new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(),
        new ProfilingLogger(new Mock<ILogger>().Object, new Mock<IProfiler>().Object));
}

private static UmbracoContext MockUmbracoContext(ApplicationContext appCtx)
{
    return UmbracoContext.EnsureContext(
        new Mock<HttpContextBase>().Object,
        appCtx,
        new Mock<WebSecurity>(null, null).Object,
        Mock.Of<IUmbracoSettingsSection>(section => section.WebRouting == Mock.Of<IWebRoutingSection>(routingSection => routingSection.UrlProviderMode == "AutoLegacy")),
        Enumerable.Empty<IUrlProvider>(),
        true);
}

private static void SetupControllerContext(UmbracoContext umbCtx, Controller controller)
{
    var webRoutingSettings = Mock.Of<IWebRoutingSection>(section => section.UrlProviderMode == "AutoLegacy");
    var contextBase = umbCtx.HttpContext;
    var pcr = new PublishedContentRequest(new Uri("http://localhost/test"),
        umbCtx.RoutingContext,
        webRoutingSettings,
        s => Enumerable.Empty<string>())
    {
        PublishedContent = MockContent(),
    };

    var routeData = new RouteData();
    var routeDefinition = new RouteDefinition
    {
        PublishedContentRequest = pcr
    };
    routeData.DataTokens.Add("umbraco-route-def", routeDefinition);
    controller.ControllerContext = new ControllerContext(contextBase, routeData, controller);
}

private static IPublishedContent MockContent()
{
    return Mock.Of<IPublishedContent>(publishedContent => publishedContent.Id == 1000);            
}

Just for completeness, to run the code you will need to pull in the following from NuGet:

    PM> Install-Package UmbracoCms.Core -Pre
    PM> Install-Package Moq

And make sure you add framework references to System.Web, System.Configuration and System.Web.ApplicationServices.

The full list of using statements are as follows:

using System;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SurfaceControllerUnitTests.Controllers;
using SurfaceControllerUnitTests.Models;
using Umbraco.Core;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Profiling;
using Umbraco.Web;
using Umbraco.Web.Mvc;
using Umbraco.Web.Routing;
using Umbraco.Web.Security;

Great to see this improved testing support with the latest Umbraco. Not seen too much being made of it yet but for me an important part of this upcoming Umbraco release is it now being so much more accessible to testing.

Monday, 25 May 2015

2015 British General Election - Progressive Alliance What If?

Rather off topic for me on this blog but thought interesting nonetheless to publish... I was taken following the personally rather disappointing UK election results by a comment by the Green MP Caroline Lucas reported in the Guardian.

Reflecting on the result, she is quoted as saying...

The system is wrong and we should have electoral reform, but that could be some time coming. So we need other ways to work together in a progressive alliance. Where it is appropriate, only one progressive candidate could stand in a seat – a sort of electoral pact...

Which got me interested in the numbers, in particular considering what the change in the result might have been if such a pact was in place for 2015. Clearly there's a lot of assumption in this - not least the fact that I'm using the hindsight of the actual results to determine what might have been different, which is rather circular. It also assumes that every voter that would have voted say Liberal Democrat would be happy to vote for another party in the "alliance", which is unlikely to be 100% the case. It would certainly need some messaging effort between now and the next election to ensure people accepted that their party preference would be counted, albeit in a different constituency.

So to look at the numbers I downloaded the full set of results for all constituencies in England, Scotland and Wales, that is available from the British Election Study website. I then found all seats the Conservative won and worked out if they would still have won if one of two alliances were in place - firstly between the Liberal Democrats and the Greens, and secondly including Labour as well.

Having found the seats that would have changed hands in this scenario, I then looked at the actual votes cast for the "alliance" parties in these constituencies. I used this to calculate a fair means of allocating which actual party would be given the seat. Again this takes some liberties with timings - in reality the choice of which party was standing (and which was standing aside) in each seat would need to be made before voting of course. But it does seem like a reasonable basis for such a decision if something like this were planned for the next election.

Finally then looking at how this pans out. Firstly, in the scenario where there's an alliance between the Liberal Democrats and the Greens, there's a fairly minor change. Five seats would change hands, which given the breakdown I've used would give the Greens a further MP and the Liberal Democrats a slightly less disastrous loss of MPs to twelve instead of the eight they retained in reality. A significant Conservative majority would still have been the result.

Where things become more dramatic is if Labour is included. Pollitically this may be far-fetched, but electorially it would likely make sense - particularly in areas such as my home region of the South West, where they are third or fourth party at best in most constituencies. In this scenario, the Greens have five MPs, Liberal Democrats three times as many at twenty four and Labour an additional twenty six. The Conservatives remain the largest party but sixty short of an overall majority.

The data and analysis is available for view and review as a Google doc here.

Thursday, 21 May 2015

Sample Site for Merchello with Umbraco

For a while now, since last Codegarden in 2014 in fact, I've been planning to take a look at Merchello, an e-commerce framework for Umbraco. In the past I've made use of uCommerce which worked well for the project but the fact that, like Umbraco, Merchello is open-source is one factor that makes it attractive to consider for future projects.

So on and off for the past few weeks I've built out a very basic store site. Really doesn't look like much and has little in the way of bells and whistles, but implements a number of the core features required for an e-commerce website, namely:

  • Product category and product pages
  • Products with variants, with price and availability indicated for the particular variant selected
  • Basket page with quantity update and option to remove
  • Billing and shipping detail collection
  • Delivery method selection and application of postage & packing costs
  • Selection of payment method
  • Integration with a credit card processing provider, Authorize.Net
  • Presentation of confirmation screen

Nothing in the above is particularly off the beaten track when it comes to Merchello - there are a number of extension points available that I've not dug into yet.

That said, in building this out I did find myself digging into a number of documentation pages and examples (plus forum posts of course) which as is often the case with a fast moving project, sometimes struggle to keep up with the latest features.

I've also followed some stricter MVC patterns I like to use with Umbraco development, which is to use route hijacking, strongly typed POCO view models and mapping with Umbraco Mapper and AutoMapper from my Umbraco content and the Merchello APIs and objects respectively.

For both those reasons think it's worth sharing and may be of use for anyone else making a start with this product. Code is up at GitHub.

Thursday, 11 December 2014

Quick Guide to the Umbraco Source Code

Just a quick and belated cross-link to an article I recently had published on the 24 Days in Umbraco website. Looking at the Umbraco source code from the perspective of someone considering code contributions to the open-source project.

24days.in/umbraco/2014/traveller-guide

Thursday, 13 November 2014

Umbraco Mapper with Nested Archetypes

Following a previous blog post I got a comment asking about dealing with mapping nested Archetypes to a view model using Umbraco Mapper. As I noted in response, it's not that straightforward - the flexibility of the Archetype package means really you have to build something fairly custom for your particular type you are mapping to. Rather than squeeze too much into a comment though, thought the topic worth a post in itself.

As before, looking for a simple example, I've modelled a football match but I've changed it a little to use a nested Archetype. There's a top-level type that contains a single field set to which a text field and two nested score types can be added. The score type has fields for the team and the score.

From the content editor's perspective it looks like this:

I'm looking to map this to a view model that looks like this:

    public class FootballMatch
    {
        public FootballMatch()
        {
            Scores = new List<FootballMatchScore>();
        }

        public string Venue { get; set; }

        public IList<FootballMatchScore> Scores { get; set; }
    }

    public class FootballMatchScore
    {
        public string Team { get; set; }

        public int Score { get; set; }
    }

Which can then be used in the views like this:

    <h3>Today's Match at @Model.TodaysMatch.Venue</h3>

    @foreach (var score in Model.TodaysMatch.Scores)
    {
        <div>@score.Team @score.Score</div>
    }        

The trick as before is to register a custom mapping for the top-level type that will be mapped, like this:

    Mapper.AddCustomMapping(typeof(FootballMatch).FullName, ArchetypeMapper.MapFootballMatch);

And the implementation looks like this:

    public static object MapFootballMatch(IUmbracoMapper mapper, IPublishedContent contentToMapFrom, string propName, bool isRecursive)
    {
        // Get the strongly typed ArchetypeModel from the given property
        var archetype = contentToMapFrom.GetPropertyValue<ArchetypeModel>(propName, isRecursive);
        if (archetype != null)
        {
            // Pull out the first fieldset
            var fieldset = archetype.FirstOrDefault();
            if (fieldset != null)
            {
                // Instantiate an instance of type we are mapping to
                var result = new FootballMatch();

                // Convert the fieldset to a dictionary and map the top-level properties
                var fieldsetAsDictionary = fieldset.Properties.ToDictionary(
                     k => FirstCharToUpper(k.Alias),
                     v => v.Value);
                mapper.Map(fieldsetAsDictionary, result);

                // Given the known aliases for the nested type, loop through and map all the properties of each
                // of these too
                var aliases = new string[] { "homeTeam", "awayTeam" };
                foreach (var alias in aliases)
                {
                    var scoresModel = fieldset.GetValue<ArchetypeModel>(alias);

                    foreach (var innerFieldSet in scoresModel)
                    {
                        var innerFieldsetAsDictionary = innerFieldSet.Properties.ToDictionary(
                            k => FirstCharToUpper(k.Alias),
                            v => v.Value);
                        var score = new FootballMatchScore();
                        mapper.Map(innerFieldsetAsDictionary, score);
                        result.Scores.Add(score);
                    }
                }

                return result;
            }
        }

        return null;
    }

As I say, it would be nice to come up with something more generic to solve this type of problem, and we have managed this to an extent on a recent project that used a number of Archetypes. The flexibility of Archetype does perhaps come at a cost here from a developer perspective. It does seem fairly unavoidable that you'll have to do something quite custom depending on what exactly you are mapping from and too.

Nonetheless once done and set up as a custom mapping within the mapper, any instance of your view model type will be automatically mapped from the given Archetype.

Sunday, 2 November 2014

Using Umbraco Mapper with the Umbraco Grid

Like most people in the Umbraco community I've been keen to download and have a play with Umbraco 7.2, released in beta last week. There's a lot of new features, but the shiniest new toy is without doubt the grid.

This allows a developer to set up a very flexible interface for the editor to manage their content in a layout that closely reflects what they'll see on the website.

When it comes to rendering out the content of the grid, it's very simple. In your view you can just make a call to CurrentPage.GetGridHtml("myGridAlias") and this will spit out the HTML wrapped with bootstrapped elements. You can pass in overrides to use a different template, and create your own.

Nothing wrong with this at all but my preferred approach when rendering out Umbraco content is to create strongly typed view models and, via a hijacked route, map the Umbraco content to this model with the help of the Umbraco Mapper package. Once done, this provides a very clean view model for front-end developers to work with, avoiding the need to work with the more complex Umbraco APIs and dynamics in the views.

Clearly the output of the grid, even if strongly typed, is still going to be relatively "loose" in that we need to be able to handle all that we allow our editors to throw at it. Nonetheless, it seemed to a useful exercise to see how Umbraco Mapper could be used to handle mapping from the Grid data type - and am pleased to say it looks to be rather straightforward.

In order to have something to map too we need our own custom class. The following has been constructed to follow the structure of the JSON format that the grid data is stored in the database:

namespace MyApp.Models
{
    using System.Collections.Generic;
    using System.Web.Mvc;
    using Newtonsoft.Json;

    public class GridContent
    {
        public IList<GridSection> Sections { get; set; }

        public class GridSection
        {
            public int Size { get; set; }

            public IList<GridRow> Rows { get; set; }

            public class GridRow
            {
                public string Name { get; set; }

                public IList<GridArea> Areas { get; set; }

                public class GridArea
                {
                    public IList<GridControl> Controls { get; set; }

                    public class GridControl
                    {
                        public object Value { get; set; }

                        public GridEditor Editor { get; set; }

                        public object TypedValue 
                        {
                            get
                            {
                                switch (Editor.Alias)
                                {
                                    case "headline":
                                    case "quote":
                                        return Value.ToString();
                                    case "rte":
                                        return new MvcHtmlString(Value.ToString());
                                    case "media":
                                        return JsonConvert.DeserializeObject<GridContentMediaValue>(Value.ToString());
                                    default:
                                        return string.Empty;
                                }
                            }
                        }

                        public class GridEditor
                        {
                            public string Alias { get; set; }
                        }
                    }
                }
            }
        }
    }
}

A key property to note is TypedValue. This is used to convert the raw value saved for the grid control element into a typed value appropriate for the content that is stored. This might be a simple string or something more complex like a media item. The implementation of this property would need to be extended to handle all the types we allow our editors to use.

For example here's a complex type representing a media item, again following the JSON structure of the saved information:

namespace MyApp.Models
{
    public class GridContentMediaValue
    {
        public int Id { get; set; }

        public string Image { get; set; }

        public string Thumbnail { get; set; }
    }
}

Then for a given page, I've created a view model that looks like this, following the structure of my document type that uses the grid data type.

namespace MyApp.Models
{
    public class GridPageViewModel
    {
        public string Heading { get; set; }

        public GridContent Grid { get; set; }
    }
}

Umbraco Mapper has a handy feature called custom mappings. These can be set up when the mapper is instantiated - usually in a single location like a base controller - to effectively say, "whenever you are given a given type on a view model to map to, use this function".

With that feature, I'm able to do this in my controller:

namespace MyApp.Controllers
{
    using System.Web.Mvc;
    using Newtonsoft.Json;
    using Umbraco.Core.Models;
    using Umbraco.Web;
    using Umbraco.Web.Models;
    using Umbraco.Web.Mvc;
    using Umbraco72a.Models;
    using Zone.UmbracoMapper;

    public class GridPageController : RenderMvcController
    {
        public override ActionResult Index(RenderModel model)
        {
            var mapper = new UmbracoMapper();
            mapper.AddCustomMapping(typeof(GridContent).FullName, MapGridContent);

            var vm = new GridPageViewModel();
            mapper.Map(CurrentPage, vm);

            return View("Grid", vm);
        }

        public static object MapGridContent(IUmbracoMapper mapper, IPublishedContent contentToMapFrom, string propName, bool isRecursive)
        {
            var gridJson = contentToMapFrom.GetPropertyValue<string>(propName, isRecursive);
            return JsonConvert.DeserializeObject<GridContent>(gridJson);
        }   
 }
}

Which finally allows me to render my grid content in a very clean, strongly typed way, like this:

@model MyApp.Models.GridPageViewModel

<div>
 <h1>@Model.Heading</h1>

 @foreach (var section in Model.Grid.Sections)
 {
  <div>
   @foreach (var row in section.Rows)
   {
    <div>
     @foreach (var area in row.Areas)
     {
      <div>
       @foreach (var control in area.Controls)
       {
        <div class="@control.Editor.Alias">
         @switch (control.Editor.Alias)
         {
          case "media":
           var media = control.TypedValue as GridContentMediaValue;
           <img src="@media.Image" />
           break;
          default:
           <span>@control.TypedValue</span>
           break;
         }                                        
        </div>
       }
      </div>   
     }
    </div>
   }
  </div>
 }
</div>

For me this looks to provide a nice balance between allowing the editor the flexibility that the grid editor provides whilst retaining the strongly typed view model and mark-up generation code in the view. Would love to hear comments from anyone else playing with the grid editor and similarly considering best practices for using it.