Passing a Value from a ViewBag to a partial View

asp.net-mvc-4partial-viewsviewbag

So my Controller's code is as follows:

private CommunityModelsContext dbCommunities = new CommunityModelsContext();

// GET: /Home/
public ActionResult Index()
{
     //retrieve the Communities 
     ViewBag.Communities = dbCommunities.Communities.ToList();
     return View();
}

And my View has this all important line to start the Partial View

<div id="LeftView" class="PartialView">@{Html.RenderPartial("CommunitiesPartial");}</div>

and in the Partial view, I'm trying to create a DropDownList (I'm still learning, this is a practice app just to see if I've understood the concepts from the asp.net tutorial), that will then take this List of entities, display one field, gets the value from the Other ("Name" and "id")

@model BuildingManagement.Models.Community.Community

@Html.BeginForm("Index","CommunityController")
{
    <div>
        @Html.LabelFor(x => x.Name)
        @Html.DropDownList("Community" , new SelectList(Model.Name,"id","Name"))
    </div>
}

Now this throws a NullReference Exception, the model is null. There is no model in the Index page and it is not bound to anything, however, the data is being sent through the ViewBag.

Ideas please?

Best Answer

Your partial is strongly typed to a model (BuildingManagement.Models.Community.Community). So you need to pass this model to the main view first:

public ActionResult Index()
{
    //retrieve the Communities 
    ViewBag.Communities = dbCommunities.Communities.ToList();
    BuildingManagement.Models.Community.Community model = ... retrieve your model
    return View(model);
}

and then since you decided to use ViewBag instead of view models you need to keep using the value you defined in this ViewBag inside your partial:

@Html.DropDownList("Community", new SelectList(ViewBag.Communities, "id", "Name"))

Of course a much better approach is to use a view model:

public class CommunityViewModel
{
    [DisplayName("Name")]
    public int Id { get; set; }
    public IEnumerable<SelectListItem> Communities { get; set; }
}

and then have your controller populate the view model and pass this view model to the view:

public ActionResult Index()
{
    //retrieve the Communities 
    var communities = dbCommunities.Communities.ToList().Select(x => new SelectListItem
    {
        Value = x.Id.ToString(), 
        Text = x.Name
    })
    var model = new CommunityViewModel
    {
        Communities = communities
    }
    return View(model);
}

and then make your view and partial strongly typed to the view model:

@model CommunityViewModel
@using (Html.BeginForm("Index","CommunityController"))
{
    <div>
        @Html.LabelFor(x => x.Id)
        @Html.DropDownListFor(x => x.Id, Model.Communities)
    </div>
}
Related Topic