1
votes

I tried to use ViewBag in a Sitecore MVC view rendering to pass some data to its relevant layout rendering but it didn't work. In standard ASP.NET MVC you can do that, but is it possible to do the same in Sitecore also? If not, then how do you pass data?

Edit

to clarify my question, here is what I was trying to do: I have a layout rendering like this:

@using Sitecore.Mvc
@using Sitecore.Mvc.Analytics.Extensions
@using Sitecore.Mvc.Presentation
@model RenderingModel
@{
Layout = null;
}
<!doctype html>
<html>
<head>....</head>
<body>
@if (ViewBag.ShowNewsletterPopup == "display")
{
    <!-- render proper html markup to show newsletter popup -->
} 
else {
  <!-- render regular html markup --> 
}
<!-- some html markup here -->
@Html.Sitecore().Placeholder("widget")
<!-- some more html markup -->

And then, inside content placeholder goes a view rendering which has a code like this:

@using Sitecore.Mvc
@using Sitecore.Mvc.Presentation
@using Sitecore.Data.Items

@model RenderingModel
@{
   ViewBag.ShowNewsletterPopup = Model.Rendering.Parameters["ShowNewsletterPopup"];

So, what I am trying to achieve is switching between two blocks of html markups depending on the settings of a view rendering which sits outside those blocks. Perhaps there is a better way to do this, but I am not sure. What I see is that the view rendering code gets compiled after layout rendering, so the code really never gets executed.

1
What exactly are you trying to do? By "relevant layout rendering", do you mean the rendering attached as the "layout"? Can you show us some code of your layout, your rendering and the placeholder?Kevin Brechbühl
@Behrooz yeah could you clarify on the question. Need more information on how you are currently trying to use the viewbag, some code will potentially help.Anicho
@Kevin, Anicho, I added some explanations. Let me know what you think. thanksBehrooz
@Behrooz I think @herskinduk has described the problem with that very well and I actually don't see a better solution than the one you have already applied. The only question may be, if the "ShowNewsletterPopup" field needs to be a rendering parameter? Or is it possible to move this to the item and ask with Sitecore.Context.Item["ShowNewsletterPopup] in both layout and the rendering? Maybe you could also add a pipeline processor in `httpRequestBegin, search for this parameter and save the value somewhere to later use it in your layout, then you could get rid of inside-out renderings.Kevin Brechbühl
@KevinBrechbühl Yeah, that's also good idea. Thank you.Behrooz

1 Answers

8
votes

I can confirm that the current behaviour of Sitecore MVC would not work. In the following scenario MVC Layout with:

@using Sitecore.Mvc
@{
    Layout = null;
    ViewBag.Message = "ViewBagData";
}
<html>
<body>
Message: @Html.Partial("View Rendering") <br>
Message: @Html.Sitecore().ViewRendering("View Rendering")
</body>
</html>

And the View Rendering:

@ViewBag.Mything

You would see the following output:

Message: ViewBagData
Message:

The underlying issue is that the ViewRendering type spins up an new HtmlHelper. Althought the ViewData is passed into this, the actual write to the dictionary backing of the ViewData is deferred (this is an MVC thing).

I would think that the desired behaviour would be for ViewBag data to behave the same as it does for @Html.Partial().

There is a related topic around TempData on the Sitecore community user voice.

You could use something like (though it feels like a smell):

Sitecore.Context.Items["Message"]

Perhaps have a look at the this video, it has a concept around rendering interdependencies.