Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC3 RenderPartial and the ViewBag

I'll try to keep this brief:

In the view

@Html.RenderPartial("myview", Model.SubModel, 
     new ViewDataDictionary()
     {
          { "thing", Model.Thing }
     })

In the myview we see that "thing" is avaiable, i.e. this produces the value of Model.Thing in the myview view:

@ViewBag.thing

Great! Simple

But I need to do something with thing (and thing can't be part of SubModel by the way), i.e. access this in my view engine or ideally in the controller, e.g.:

public ActionResult myview(SubModelType vm)
{
    var thing = ViewBag.thing; // oh dear this doesnt exist.. but is there when the view is rendered

So my question is, if the ViewBag is available in the resulting myview, it must be being passed around somehow in the httpcontext, or in the controllercontext somewhere right? Does anyone know why it's not available in the controller but is in the view and how I might be able to access this?

Edit

Sorry I missed a vital point here! It's when "myview" is posted back to the controller, invoking an action called myview where I would expect the ViewBag rendered to myview to be available. But of course it's not, it's been used in "myview" and that's it. So if I want to use it in the myview action I'm going to need to store in the ViewBag in that view OR set some value of the viewmodel so that it can be posed back to the action.

Does that make sense?

like image 380
Mr AH Avatar asked Jan 18 '26 17:01

Mr AH


1 Answers

Sorry I missed a vital point here! It's when "myview" is posted back to the controller, invoking an action called myview where I would expect the ViewBag rendered to myview to be available.

Oh no, you cannot be possibly expecting anything like that. That's not how ASP.NET MVC works. When you send an HTTP request to a controller action the default model binder will intercept this request and look in the posted values from the request and bind them to your action argument:

[HttpPost]
public ActionResult myview(SubModelType vm, ThingViewModel thing)
{
    ...
}

This obviously assumes that those thing values were part of the original request. So for example if you submit a form you should include corresponding fields inside this form that the model binder could use.

Think of it that way: an ASP.NET MVC controller action could be invoked from any client. For example from an iPhone application. And as you know there's no such notion as ViewBag in iOS. All that will happen is that the default model binder will look at the POSTed values and attempt to hydrate the view models that your action is taking as arguments.

If on the other hand you cannot make those thing values as part of the request (by including corresponding input fields in the form) you could only send the ID of this thin from a hidden field and then inside your controller action use this ID to query your underlying data-store to retrieve the thing from the same place you retrieved it initially when you first rendered this form.

Some people might also suggest you storing the Thing inside the Session and then reading the value back from the Session in your POST action. I am not from those people. It's an alternative approach though.

like image 54
Darin Dimitrov Avatar answered Jan 20 '26 20:01

Darin Dimitrov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!