Using Html.RenderContentData with IView or ViewEngine does not use the templateTag parameter.

Vote:
 

I've been playing around with custom rendering with IContentDataExtensions.RenderContentData with different tags and I don't want to register alot of TemplateModels just to get to my view.

In my example

@Html.RenderContentData(myContentData, false, "MyTag")

It seems like there are some ideas in MvcContentRenderer that would support this by using IViews and checking ViewEngines but it doesn't really work (see detailed description below).

The problem is MvcContentRenderer doesn't really use "MyTag" that I send as parameter.

The problem seems to be that the method IContentDataExtensions.RenderContentData(this HtmlHelper html, IContentData contentData, bool isContentInContentArea, string templateTag) only determines which ModelTemplate to use and sends it as a parameter to the overload 

RenderContentData(this HtmlHelper html, IContentData contentData, bool isContentInContentArea, TemplateModel templateModel, IContentRenderer contentRenderer) which in turn calls contentRenderer.Render(HtmlHelper helper, PartialRequest partialRequestHandler, IContentData contentData, TemplateModel templateModel).

contentRenderer in this case is by default MvcContentRenderer.

If the TemplateModel is TemplateTypeCategories.MvcPartialView, the MvcContentRenderer.Render method has nice parts to let you customize your rendering by implementing the IView interface. It also has a mechanism to try to resolve your view by asking the ViewEngines for a view called either the name + tag, or simply the name from the TemplateModel.

An example of the IView implementation are described in Jonas Bergqvist's blog http://world.episerver.com/blogs/Jonas-Bergqvist/Dates/2013/6/Hidden-template-functionality-in-the-MVC-implementation/.

But I would like to have the "magic find your view" functionality in MVC and it's a bit tricky since my implementation does not receive the tag or the TemplateModel.

I have also noted that the ViewEngine mechanism doesn't receive the tag from my parameter.

Both the IView and ViewEnginge mechanism checks the ViewData for the tags, but the parameter from RenderContentData nor the TemplateModel used is passed.

So my question is: Is something broken, or am I trying to do something in a way where it's not meant to be used? Do I really need to register TemplateModels just to get a tag specific path?

#114901
Dec 31, 2014 0:16
Vote:
 

It sounds like a bug when the View Engine "mechanism" doesn't receive the tag. This should be fixed. I will try this out tomorrow.

#115412
Jan 14, 2015 15:45
Vote:
 

Cool, I was testing with the latest around christmas (think it was 7.18 or something, don't have the code around). I can check for tomorrow and give you more details if you need.

Thanks!

#115414
Jan 14, 2015 15:51
Vote:
 

The tag will only be used by the TemplateResolver to get the correct view, it will not be send to the block renderer as you wrote. I think it could be a good feature to set that in the RouteData collection. I will create a feature request for this.

#115680
Jan 16, 2015 8:36
Vote:
 

Cool, that would be great! Thnx!

#115682
Jan 16, 2015 8:50
Vote:
 

stumbled on the same issue.. and only now realized at what time Alf posted the original question ;)

#120707
Apr 22, 2015 22:21
Vote:
 

Anyway Jonas, any bug # for reference? Seems like still present in 8.0+

#120708
Apr 22, 2015 22:22
Vote:
 

It's the the CMS backlog. I can't say when it's going to be fixed, but it's at least in the backlog. 

#120715
Apr 23, 2015 8:49
Vote:
 

Been there too, so I ended up with this simple "fix":

public class TemplateTagContext : IDisposable
{
    private readonly HtmlHelper _helper;
    private readonly object _originalTag;

    public TemplateTagContext(HtmlHelper helper, string tag)
    {
        _helper = helper;
        _originalTag = _helper.ViewContext.ViewData["Tag"];
        _helper.ViewContext.ViewData["Tag"] = tag;
    }

    public void Dispose()
    {
        _helper.ViewContext.ViewData["Tag"] = _originalTag;
    }
}

Html helper extension:

public static TemplateTagContext BeginTemplateTag(this HtmlHelper helper, string tag)
{
    return new TemplateTagContext(helper, tag);
}

And finally in the view:

@using (Html.BeginTemplateTag("MyTag"))
{
    Html.RenderContentData(myContentData, false);
}
#120716
Edited, Apr 23, 2015 8:50
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.