0

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

3
  • If the issue you're having is something to do with the partial view not rendering properly, read this. Otherwise we may need more specific information about the issue you're facing. Also, you shouldn't be using ViewData or TempData to persist view specific information. You should be using view models. Commented Mar 3, 2015 at 17:47
  • Everything renders ok. I'm using this from inside a View, to be shown by the View. e.g. setting particular CSS classes for particular pages. The issue is ViewData being set my the partial doesn't propagate up Commented Mar 3, 2015 at 18:02
  • You can still use HttpContext.Current.Items["something"] Commented Mar 4, 2015 at 6:17

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Brilliant - many thanks for the poke to use HttpContext.Items - we use this for "per request" caching currently, but I didn't think of using it to solve this problem! This worked a charm - cheers.
3

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.

1 Comment

I feared it was a one-way propagation, Thanks for the clarification, Chris.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.