I am using a ViewModel to retrieve entered data in controller action. But the ViewModel is getting empty values in it\'s properties. I am creating one partial view
You cannot bind a dropdownlist to a collection of complex objects - in your case IEnumerable<tblCurrentLocation>
and IEnumerable<tblStream>
A <select>
tag only posts back a single value (the value of the selected option) so in the POST method the DefaultModelBinder
is attempting to so testName.tblCurrentLocations = "1"
(assuming the value of the selected option is 1
) which of course fails and the property is set to null
You need a view model containing properties that you want to bind to (and ideally will include the SelectList
's used by the DropDownListFor()
helper)
public class LookUpViewModel
{
[Display(Name = "Location")]
[Required(ErrorMessage = "Please select a location")]
public int SelectedLocation { get; set; }
[Display(Name = "Stream")]
[Required(ErrorMessage = "Please select a stream")]
public int SelectedStream { get; set; }
public SelectList LocationList { get; set; }
public SelectList StreamList { get; set; }
}
Then in the view
@Html.LabelFor(m => m.SelectedLocation)
@Html.DropDownListFor(m => m.SelectedLocation, Model.LocationList, "-Please select-")
@Html.ValidationMessageFor(m => m.SelectedLocation)
@Html.LabelFor(m => m.SelectedStream)
@Html.DropDownListFor(m => m.SelectedStream, Model.StreamList, "-Please select-")
@Html.ValidationMessageFor(m => m.SelectedStream)
and in the controller
public ActionResult Edit()
{
LookUpViewModel model = new LookUpViewModel();
ConfigureViewModel(model);
return View(model);
}
[HttpPost]
public ActionResult Edit(LookUpViewModel model)
{
if (!ModelState.IsValid)
{
ConfigureViewModel(model);
return View(model);
}
// model.SelectedLocation will contain the value of the selected location
// save and redirect
}
private void ConfigureViewModel(LookUpViewModel model)
{
// populate your select lists
var locations = from o in rosterManagementContext.tblCurrentLocations select o;
model.LocationList = new SelectList(locations, "LocationId", "Location");
.... // ditto for streams
}
Note as also indicated in Maximilian's answer, your view model should only contain properties your need for the view. Your controller is responsible for populating the values. A view model should never make a call to a database - it should not even be aware that one exists.
This answer will not solve your problem directly, but first of all I recommend you to outsource the filling of the ViewModel at least to the controller (Because otherwise it will recreate the DBContext every time the constructor is called). A ViewModel should only contain data - no logic. And secoundly I would use the DBContext in an Using statement
ViewModel:
public class LookUpViewModel
{
[Required]
public virtual IEnumerable<tblCurrentLocation> tblCurrentLocations { get; set; }
[Required]
public virtual IEnumerable<tblStream> tblStreams { get; set; }
Controller:
public ActionResult Foo()
{
LookUpViewModel ViewModel = new LookUpViewModel();
using(RosterManagementEntities rosterManagementContext = new RosterManagementEntities())
{
ViewModel.tblCurrentLocations = from o in rosterManagementContext.tblCurrentLocations select o;
ViewModel.tblStreams = from o in rosterManagementContext.tblStreams select o;
}
return View(ViewModel);
}