Unable to access the ContentArea containing a block

Vote:
 

I have a page ContentArea that contains a list of blocks where every other block gets a certain CSS class. Do accomplish this, each block view asks what its index in the ContentArea is when it's being rendered to determine if it's an even or odd index. To do that I used the approach of this blog post:

http://world.episerver.com/blogs/Per-Magne-Skuseth/Dates/2013/8/Letting-your-blocks-know-where-they-are/

and it all works great. I'm not setting up a new site where we want to do the same thing. I copied the code for getting the ContentArea and the index straight over, but for some reason on the new site, the ParentActionViewContext property is null. It seems like for some reason on the new site, the request maybe is not considered a child request, but I can't find the difference. Here is my code:

Rendering the ContentArea property on the parent page:

@Html.PropertyFor(m => m.CurrentPage.DepartmentalSupportBlocks)


Asking for the index in the block view:

@model TLGMVCFranWeb.Models.Blocks.DepartmentalSupportBlock
@{ 
    Guid instanceID = Guid.NewGuid();
    var alignment = Html.ContentAreaIndex(((IContent)Model).ContentLink) % 2 == 0 ? "right" : "left";

   }

And the ContentAreaIndex method:

public static int ContentAreaIndex(this HtmlHelper helper, ContentReference contentLink)
{
int index = -1;

try
{
ContentArea contentArea = helper.ViewContext.ParentActionViewContext.ViewData.Model as ContentArea;
if (contentArea == null) return index;

IEnumerable items = EPiServer.Editor.PageEditing.PageIsInEditMode ? contentArea.Items : contentArea.FilteredItems;

index = items.Select(p => p.ContentLink).IndexOf(contentLink);
}
catch (Exception ex) 
{}

return index;
}

The only difference I see between this and the other site (other than the page and block types) are the other site uses an overidden PropertyFor to render the ContentArea in order to do some conditional work on the blocks, and it also uses a custom ContentArea renderer. But since the referenced blog uses none of that, it doesn't seem like that would be the problem here. Any idea why helper.ViewContext.ParentActionViewContext is null?

#144868
Feb 19, 2016 22:27
Vote:
 

I removed the overridden PropertyFor and custom ContentArea renderer from the working project and it still works so I compared the call stack. It looks like in the working project, somewhere inside of EPiServer it executes it as a child action, however in the new project it doesn't.

New project call stack where ParentActionViewContext is null:

EPiServer.dll!EPiServer.Web.Mvc.MvcContentRenderer.HandleRenderTemplateWithViewEngine(System.Web.Mvc.HtmlHelper helper, EPiServer.Core.IContentData contentData, EPiServer.DataAbstraction.TemplateModel templateModel)Unknown EPiServer.dll!EPiServer.Web.Mvc.MvcContentRenderer.Render(System.Web.Mvc.HtmlHelper helper, EPiServer.Web.Mvc.PartialRequest partialRequestHandler, EPiServer.Core.IContentData contentData, EPiServer.DataAbstraction.TemplateModel templateModel)Unknown

EPiServer.dll!EPiServer.Web.Mvc.Html.IContentDataExtensions.RenderContentData(System.Web.Mvc.HtmlHelper html, EPiServer.Core.IContentData contentData, bool isContentInContentArea, EPiServer.DataAbstraction.TemplateModel templateModel, EPiServer.Web.Mvc.IContentRenderer contentRenderer)Unknown

EPiServer.dll!EPiServer.Web.Mvc.Html.ContentAreaRenderer.RenderContentAreaItem(System.Web.Mvc.HtmlHelper htmlHelper, EPiServer.Core.ContentAreaItem contentAreaItem, string templateTag, string htmlTag, string cssClass)Unknown

EPiServer.dll!EPiServer.Web.Mvc.Html.ContentAreaRenderer.RenderContentAreaItems(System.Web.Mvc.HtmlHelper htmlHelper, System.Collections.Generic.IEnumerable<EPiServer.Core.ContentAreaItem> contentAreaItems)Unknown

EPiServer.dll!EPiServer.Web.Mvc.Html.ContentAreaRenderer.Render(System.Web.Mvc.HtmlHelper htmlHelper, EPiServer.Core.ContentArea contentArea)Unknown 

EPiServer.dll!EPiServer.Web.Mvc.Html.ContentAreaExtensions.RenderContentArea(System.Web.Mvc.HtmlHelper htmlHelper, EPiServer.Core.ContentArea contentArea)Unknown 

App_Web_myevwxkt.dll!ASP.util_views_shared_displaytemplates_contentarea_ascx.__Render__control1(System.Web.UI.HtmlTextWriter __w, System.Web.UI.Control parameterContainer) Line 4C#

Original project where ParentActionViewContext is set:

EPiServer.dll!EPiServer.Web.Mvc.PartialRequest.RenderAction(System.Web.Mvc.HtmlHelper helper, string action, string controller, object routeValues)Unknown EPiServer.dll!EPiServer.Web.Mvc.MvcContentRenderer.Render(System.Web.Mvc.HtmlHelper helper, EPiServer.Web.Mvc.PartialRequest partialRequestHandler, EPiServer.Core.IContentData contentData, EPiServer.DataAbstraction.TemplateModel templateModel)Unknown 

EPiServer.dll!EPiServer.Web.Mvc.Html.IContentDataExtensions.RenderContentData(System.Web.Mvc.HtmlHelper html, EPiServer.Core.IContentData contentData, bool isContentInContentArea, EPiServer.DataAbstraction.TemplateModel templateModel, EPiServer.Web.Mvc.IContentRenderer contentRenderer)Unknown 

EPiServer.dll!EPiServer.Web.Mvc.Html.ContentAreaRenderer.RenderContentAreaItem(System.Web.Mvc.HtmlHelper htmlHelper, EPiServer.Core.ContentAreaItem contentAreaItem, string templateTag, string htmlTag, string cssClass)Unknown 

EPiServer.dll!EPiServer.Web.Mvc.Html.ContentAreaRenderer.RenderContentAreaItems(System.Web.Mvc.HtmlHelper htmlHelper, System.Collections.Generic.IEnumerable<EPiServer.Core.ContentAreaItem> contentAreaItems)Unknown 

EPiServer.dll!EPiServer.Web.Mvc.Html.ContentAreaRenderer.Render(System.Web.Mvc.HtmlHelper htmlHelper, EPiServer.Core.ContentArea contentArea)Unknown 

EPiServer.dll!EPiServer.Web.Mvc.Html.ContentAreaExtensions.RenderContentArea(System.Web.Mvc.HtmlHelper htmlHelper, EPiServer.Core.ContentArea contentArea)Unknown 

App_Web_zaun2obg.dll!ASP.util_views_shared_displaytemplates_contentarea_ascx.__Render__control1(System.Web.UI.HtmlTextWriter __w, System.Web.UI.Control parameterContainer) Line 4C#

Notice the bold frames where it begins to differ between the two. Yet I'm calling both the same way. Here's how I call them respectively:

@Html.PropertyFor(m => m.CurrentPage.WallBlocks)
@Html.PropertyFor(m => m.CurrentPage.DepartmentalSupportBlocks)

Any ideas?


#144927
Edited, Feb 22, 2016 17:55
Vote:
 

I found the problem. I was correct in thinking that the ParentActionViewContext was null because the block was not being executed as a child view. The reason seems to be because my block did not have a controller. It looks like EPiServer will render Blocks that have a controller as child Actions, but those that do not have a controller as part of the same request. I guess this is the reason why it's recommended to not use a controller for your Blocks for efficiency reasons. However, if you need information about the parent ContentArea, it seems you do need to have a controller.

P.S. Make sure you return PartialView(...) not View(...) from your block controller so you don't spend an extra couple hours trying to figure out why it's yelling at you saying,

The model item passed into the dictionary is of type 'Castle.Proxies.[MyBlock]Proxy', but this dictionary requires a model item of type '[My default layout's model type]'

#145441
Mar 03, 2016 18:37
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.