Reputation: 4578
I had previously been using TempData to set things like a "body css class", which then pages and partials could override.
I've now moved over to ViewData after realising that TempData uses sessions, however setting a ViewDataDictionary's value inside the partial basically gets ignored when it gets back up to the page - and never propagates up the layout hierarchy.
I've tried calling "RenderPartial" from inside my Page, and using the override which allows me to specify the ViewData to pass over:
Layout:
Page:
@{
var cssClass = (ViewData["something"] != null) ? ViewData["something"].ToString() : "";
}
<body class="@cssClass">
Page:
@{
ViewData["something"] = "blah";
Html.RenderPartial("MyPartial", ViewData)
}
Partial:
@{
ViewData["something"] += " blah";
}
When I debug inside my Layout, I can see that ViewData["something"] is "blah" - the partial didn't set it correctly.
When I was using TempData this would work ok. I don't really want to go back to using TempData because of ASP session locking and its effect on concurrent requests.
Has anybody got this to work before? Am I overlooking something?
Thanks
Upvotes: 0
Views: 889
Reputation: 12142
So this is a one way propagation as you've discovered if you want to set data in partial and return to parent view you can use the HttpContext
which is not very cool but it works:
Parent:
@{
HttpContext.Current.Items["Something"] = "blah";
Html.RenderPartial("_Partial");
}
@HttpContext.Current.Items["Something"];
Partial:
@{
HttpContext.Current.Items["Something"] = "somethingelse";
}
Outputs "somethingelse" in the parent.
Alternatively and the way it's typically done, if you're bypassing TempData, is via the parent model or a temp model:
Model:
public class MyTempModel
{
public string Something { get; set; }
}
Parent:
@{
var tmod = new MyTemModel()
{
Something = "blah"
};
Html.RenderPartial("_Partial", tmod);
}
@tmod.Something;
Partial:
@model MyTempModel
@{
tMod.Something = "somethingelse";
}
Outputs "somethingelse" in the parent.
Upvotes: 3
Reputation: 239350
Each view has its own ViewData
. By default, Razor fills views further down the hierarchy with the ViewData
of their parents, but this is one-way. For example, if you do something like:
SomeView.cshmtl
@{ ViewData["foo"] = "bar"; }
@Html.Partial("_SomePartial")
SomePartial.cshtml
@ViewData["foo"]
The result of the partial will be "bar" as you'd expect. But, if you did something like:
SomeView.cshtml
@Html.Partial("_SomePartial")
@ViewData["foo"]
_SomePartial.cshtml
@{ ViewData["foo"] = "bar"; }
Nothing would be printed, as ViewData["foo"]
doesn't exist in the view data for the parent view, only in the view data for the partial.
Upvotes: 3