Toby Holland Toby Holland - 1 month ago 19
C# Question

MVC Viewmodel partially null

My View is bound to this model

public class HomepageViewModel
{
public HomepageViewModel()
{
Regions = new List<TMRegion>();
}

public List<TMRegion> Regions { get; set; }

public int SelectedRegion { get; set; }

public SelectList SelectListRegions
{
get
{
List<SelectListItem> items = new List<SelectListItem>();
foreach (var tmRegion in Regions)
{
items.Add(new SelectListItem()
{
Value = tmRegion.Value.ToString(),
Text = tmRegion.Display
});
}
return new SelectList(items);
}
}
}


My view is like this -

@model ProSell.Admin.Models.ViewModels.HomepageViewModel

@using (Html.BeginForm("Index", "Search", FormMethod.Post, new { viewModel = Model }))
{
@Html.HiddenFor(m=>m.Regions)


@Html.DropDownListFor(model => model.SelectedRegion, Model.SelectListRegions.Items as List<SelectListItem>, "Select a region")

<input type="submit"/>


}

My controller populates Regions like this -

// GET: Search
public async Task<ViewResult> Index(HomepageViewModel viewModel)
{
if (viewModel.Regions.Count == 0)
{
viewModel = new HomepageViewModel();
JavaScriptSerializer js = new JavaScriptSerializer();
viewModel.Regions =
js.Deserialize<TMRegion[]>(
await _ApiConsumer.ExecuteGetMethod("myurlinhere"))
.ToList();

}

return View(viewModel);
}


The Drop down is populated in the view. When i select a region and submit the HomepageViewModel has the SelectedRegion correctly set to whatever id was selected, but the collection of Regions is empty.

How do I maintain the list in the model on submit?

Answer

Generally you should attempt to reduce the amount of data the client sends back to the server especially with collections since it's far more efficient for the server to make a database call to retrieve the collection than have it passed back with the form data.

As Stephen said you can re-populate the collections Regions from your controller or if you need it when returning the view due to ModelState error you can add the population code into your model's constructor.

Also you can clean up your collection property like this:

public IEnumerable<SelectListItem> SelectListRegions
{
    get
    {
        return Regions.Select(x => new SelectListItem
        {
            Text = x.Display,
            Value = x.Value.ToString()
        });
    }
}

and in your View:

@Html.DropDownListFor(model => model.SelectedRegion, Model.SelectListRegions, "Select a region")
Comments