Can't access ViewBag in a partial view in ASP.NET MVC3
Asked Answered
R

8

60

I have a controller calling a view. In the view there is a PartialView called be @Html.Partial("ViewName", model). This works fine.

But in the controller I wish to put something in the viewbag what would be hard to put in the viewmodel I pass to the view. The main view have no problem accessing the ViewBag, but in the PartialView it does not return anything.

Is it possible to use the ViewBag in this case or should I "hack" this data into the model I pass to the view (and the model I pass to the PartialView, and the model I pass to the PartialView nested in the first PartialView)?

Reverberate answered 20/4, 2011 at 11:53 Comment(3)
One thing to remember about dynamic is that it's case sensitiveNonah
My mistake, I used @Html.Action in the chain without remembering it.Reverberate
It's very silly that I actually earned a gold badge for this very poor question. I'm sort of ashamed.Reverberate
F
63

That should work without any problems. In my HomeController Index action I add a message to the ViewBag:

ViewBag.Message = "Welcome to ASP.NET MVC!";

On the Index View I add the partial view:

@Html.Partial("ViewName")

And on the partial view I render the message:

@ViewBag.Message

From the comments below: there seems to be a problem when you pass a model to the partial view. Then you can refer to the original ViewBag with

@ViewContext.Controller.ViewBag.Message
Forras answered 20/4, 2011 at 21:54 Comment(6)
I've found that if you use @Html.Partial("ViewName", Model) then the rest of the viewbag will not be available.Piecrust
Are you sure? For me this is only the case when you specify explicit viewData. Like this: @Html.Partial("ViewName", Model, ViewData) otherwise the ViewBag is fully accessible.Lixivium
I know this is a bit old, but for future reference, I solved this by using ViewContext.Controller.ViewBag.Property. Of course this means that the ViewBag property you are trying to access was set in the controller, but I think that is a common enough case.Shwa
I know we should not be saying thanks but this was upsetting me until I read TehOne's comment. You saved my life TehOne :P!!Sidras
This only ever happens to be when I load a partial within a partial. @TehOne's solution worked for meSawtoothed
@Shwa Would you take a look at my question too, please? #71446887Milestone
G
35

If you are using an overload of the Html.Partial() where viewData is one of the input parameters, for example:

@Html.Partial("PartialViewName", Model, new ViewDataDictionary(ViewBag))

then your partial view will not see data from your original ViewBag.

Remove new ViewDataDictionary(ViewBag), so you should write

@Html.Partial("PartialViewName", Model)
Gabrielson answered 17/6, 2013 at 11:56 Comment(4)
Please note, that I've found the cause of the error already, so it might be a little hard for this answer to have any relevance.Reverberate
@SoonDead but this answer still relevant for googlers comes here :)Attorney
@EvgenyLevin This is true.Reverberate
You should initialize your view data dictionary with new ViewDataDictionary(ViewData). This will copy all original view data values, including the ViewBag, to the new dictionary. Details see here: https://mcmap.net/q/330419/-renderpartial-and-viewbagRowles
N
11

In a comment TehOne said:

I know this is a bit old, but for future reference, I solved this by using ViewContext.Controller.ViewBag.Property. Of course this means that the ViewBag property you are trying to access was set in the controller, but I think that is a common enough case.

Which is what worked for me.

Numbing answered 20/4, 2011 at 11:53 Comment(0)
D
9

Recently I was experiencing same problem, but the answers here were just workarounds as they propose not to use the overload of Html.Partial using viewData. But if you had to use these overloads I believe the correct answer is:

@Html.Partial(
     "PartialViewName",
     model_object,
     new ViewDataDictionary() { { "Value1InViewBag", ViewBag.Value1InViewBag }, { "Value2InViewBag", ViewBag.Value2InViewBag } }
)

I think this answer should be used if you need to pass different ViewDataDictionary (e.g. I us it for changing HtmlFieldPrefix) and because in the view you should know, what partial view wil need in ViewBag, so it should not be problem to name all the parameters from ViewBag to be copied into new ViewBag used in partial view (apparently ViewBag uses values from ViewData).

Decoteau answered 22/5, 2015 at 22:29 Comment(0)
S
2

> In a general scenario, when you use Html.Partial;

Html.Partial("partialViewName");

The Model that is sent for parentView, can be used for in the partialViewName. Moreover, the ViewData which is send for parentView can also be used for partialViewName.

> As a special case, when you use Html.Partial and if you want to send Model..

Html.Partial("partialViewName", newModel);

You cannot reach the Model which was sent for parentView. Therefore, from now on the Model which is active in the partialViewName is the newModel. The viewData which is send for parentView can be used also for partialViewName.

> As a special case, when you use Html.Partial and if you want to send ViewDataDictionary..

The Model which is send for parentView can be used also for partialViewName

I.

@Html.Partial("partialViewName", new ViewDataDictionary { { "key", value }, { "key2", value2 }  })

Here, the ViewData which was sent for parentView overwrite by 'new ViewDataDictionary'.

Here, If there is a ViewBag which is for parentView, you cannot reach that if you write the code like above one.

II.

ViewDataDictionary viewDataDictionary =  new ViewDataDictionary();
viewDataDictionary.Add("key", value);
viewDataDictionary.Add("key2", value2);
@Html.Partial("partialViewName", viewDataDictionary)

This usage is same as first one (I.).

III.

ViewDataDictionary viewDataDictionary = ViewData; //If you use this code block,  ViewBag which is sent for parent View is not lost.
viewDataDictionary.Add("key", value);
viewDataDictionary.Add("key2", value2);
@Html.Partial("partialViewName", viewDataDictionary)

With this code block, You can reach the ViewData and ViewBag which are sent for parentView in the partialViewName

Salzman answered 12/4, 2019 at 11:37 Comment(0)
T
1

I was having this same problem with a very basic page:

@Html.Partial("_AppIntro")

<div class="form-group row">
    <div class="col-md-10">
        <a href="/Ag/Application/1" class="btn btn-default btn-primary">Next</a>
    </div>
</div>

And the partial view contained only text with some references to ViewBag to fetch some dynamic values passed from the controller. It turned out that the name of the partial view mattered. Removing the partial page and recreating it with Add -> View -> MVC 5 View but naming the page _AppIntro.cshtml fixed it.

Tramontane answered 25/10, 2017 at 15:28 Comment(0)
S
0

My senario was, I had partial view with Model IEnumerable<SampleModel> However I had to pass using, coz Model.SampleModelList can be null

@Html.Partial("PartialViewName", Model.SampleModelList, new ViewDataDictionary())

The simple solution was since PartialView is also now part of View every element on View can be accessed by PartialView so I did set the ViewBag data to data-element on View html, instead of ViewBag.

<div class="showcase-heading" id="dvValue" data-id="@Model.ContentId">@Model.Name</div>
Superload answered 1/8, 2015 at 19:30 Comment(0)
B
0

In my case @ViewContext.Controller.ViewBag.Message didn't work as well. I have a partial view that is referenced from different controllers with different models, inherited from a base model class. In this case the Controller.ViewBag comes as null.

My solution is:

@{
var dummy = ViewContext.Controller.ViewData.TryGetValue("CommonRules", out object rules);
}
...
@Html.Raw(rules)
Beabeach answered 31/7, 2020 at 16:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.