ContentArea rendering ViewModels?

Member since: 2010

If I want to render a couple of blocks on the page, I would define a ContentArea:

        [Display(
            GroupName = SystemTabNames.Content,
            Order = 320)]
        [CultureSpecific]
        public virtual ContentArea MainContentArea { get; set; }

This content area "knows" how to render the blocks, if their model is, let's say, EditorialBlock2 - which eventually inherits from EPiServer.Core.BlockData.

However, if I define a EditorialBlock2ViewModel, and add @model PROJECT.Web.Views.Shared.EditorialBlock2ViewModel to EditorialBlock2.cshtml, I get the following error:

The model item passed into the dictionary is of type 'Castle.Proxies.EditorialBlock2Proxy', but this dictionary requires a model item of type 'PROJECT.Web.Views.Shared.EditorialBlock2ViewModel'.

The controller looks like this:

public ActionResult EditorialBlock2(EditorialBlock2 currentBlock)
{
var viewModel = new EditorialBlock2ViewModel();
AutoMapper.Mapper.Map(currentBlock, viewModel);

return PartialView(viewModel);
}

This is how MainContentArea on the page looks like:

@Html.PropertyFor(m => m.MainContentArea, new { CssClass = "row equal-height" })

Is there a way to make this work? Would I need to have @Html.RenderAction that creates a list of ViewModels of specific types? Than I wouldn't be able to add blocks of random type?

 
#64319 Dec 17, 2012 18:32
  • I think you are being tricked by an implemented Index action defined in a base class of BlockController<T>. Are you inheriting from BlockController<T>? Try to rename your action to

    public override ActionResult Index(EditorialBlock2 currentBlock){...}

     

    If you are only mapping propertied from the Block type to the View Model, you could skip the Controller completely and create a view (using the BlockType as model directly) and place the view in the View/Shared folder. Name the view EditorialBlock2.cshtml.

    /Sørby

     

    #64323 Dec 18, 2012 0:22
  • Member since: 2010

    Hi, Petter,

    Thank you very much for your answer! It solved my problem.

    This is how the controller looks like now:

    public override ActionResult Index(EditorialBlock2 currentBlock)
    {
    var viewModel = new EditorialBlock2ViewModel();
    AutoMapper.Mapper.Map(currentBlock, viewModel);

    return PartialView("EditorialBlock2", viewModel);
    }

     

    I prefer to have a ViewModel, this is just for a base code, most probably in the real world, I would do some other stuff, other than just mapping.

     

    #64335 Dec 18, 2012 9:57
  • Hi,

    I'd just like to add that only having a partial view like Petter described won't only result in less code but also significantly better performance as having the controller means the block will be rendered with RenderAction and thereby forcing a full "MVC cycle" for each block on a page.

    The most pragmatic way always depends on the unique case for each site of course, but I thought it would be good to mention in this thread as the performance implications may not be obvious.

    #64338 Dec 18, 2012 10:47
  • Member since: 2010

    Thx a lot for your valuable input, Joel.

    I think it would be good to use this approach, for example, when having Image block (with only ImageUrl and ImageAlt), than there is no need to do only mapping.

    #64373 Dec 18, 2012 15:45