Blog about tips & tricks for CMS enhancement

eric.petersson

Render Nested Content with custom ViewModel in Umbraco 8


In today's post we will look into rendering a start page in Umbraco 8 with a custom view model. Sometimes we developers demand a bit of control in order to achieve a best suited structure for a customer's site or web solution. Let's dig into the code!

The Controller

Our start page will consist of one property only - nested content. We will name this property to SubContentArea since we will use different elements to fill our area (nested content area) with elements.

We will start of by inheriting from the RenderMvcController class in Umbraco to pipe further our request of rendering content with the CurrentTemplate ActionResult. We will transform our content to be using the StartPage template defined in Umbraco and finally, we will send the content to transform to a StartPageViewModel.

public class StartPageController : RenderMvcController
{
    public override ActionResult Index(ContentModel model)
    {
        var startPage = model.Content as StartPage;
        var viewModel = new StartPageViewModel(startPage);

        return CurrentTemplate(viewModel);
    }
}

To cast your model.Content as StartPage you need to tell the Models Builder in Umbraco 8 to be static so you can use the Models folder's generated content in your AppData path. Just specify in your web.config the following:

<appSettings>
    <add key="Umbraco.ModelsBuilder.Enable" value="true"/>
    <add key="Umbraco.ModelsBuilder.ModelsMode" value="AppData"/>
</appSettings>

The ViewModel

We will take the content of the StartPage and pipe it down to the StartPageViewModel and create a custom property called Blocks. This property will be of the IEnumerable<IPublishElement> of Umbraco's Core implementation since we want our nested content properties to contain the object's entire properties.

public class StartPageViewModel
{
    public StartPageViewModel(StartPage startPage) : base(startPage)
    {
        Blocks = startPage.SubContentArea;
    }

    public IEnumerable<IPublishedElement> Blocks { get; set; }
}

The View

Once we have set our Controller and ViewModel up, we will render the content of the editors.

In your StartPage.cshtml view, inherit StartPageViewModel in the UmbracoViewPage template.

We will render each nested property content with a foreach and we will route the proper way  for the partial to present the properties, since you may have different allowed element types in your nested content area. In the case below, we have two different element types named BlockContent and FullImageBlock.

@inherits UmbracoViewPage<MyWebsite.Web.Models.ViewModels.StartPageViewModel>
@using ContentModels = Umbraco.Web.PublishedModels;

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@if (Model.Blocks != null && Model.Blocks.Any())
{
    foreach (var block in Model.Blocks)
    {
        switch (block.ContentType.Alias)
        {
            case ContentModels.BlockContent.ModelTypeAlias:
                @Html.Partial(nameof(ContentModels.BlockContent), block)
                break;
            case ContentModels.FullImageBlock.ModelTypeAlias:
                @Html.Partial(nameof(ContentModels.FullImageBlock), block)
                break;
        }
    }
}

Today we looked into bringing nested content properties to presentation in Umbraco 8 with a custom ViewModel. Hope you enjoyed it!