Reputation: 104
I'm working on an app for a cycling team. I have to add riders to a ride. To do this I want the user te select the date of a ride, select a value for the point of this ride an then have a list of the members of the team where the user selects which member participated on the ride.
It works fine until I post the form. when I debug my model in the controler the list of Riders in de model counts 4 riders (which is correct as I have 4 riders in my Db for testing) but the riders are null when I check the list.
Can anyone help me, I dont know what I'm doing wrong.
this are the viewmodels I use:
public class RiderViewModel
{
public string Id { get; set; }
public string FulllName { get; set; }
public bool IsChecked { get; set; }
}
public class RideViewModel
{
public string RideId { get; set; }
[Display(Name = "Datum")]
[DataType(DataType.Date)]
[Required(ErrorMessage = "Datum is verplicht")]
public DateTime Date { get; set; }
[Display(Name = "Aantal punten")]
[Required(ErrorMessage = "Een waarde voor het puntenaantal is verplicht")]
public int Punten { get; set; }
[Display(Name = "Leden")]
public List<RiderViewModel> Riders { get; set; }
}
this is my controler:
//POST Rides/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(RideViewModel model)
{
if (ModelState.IsValid)
{
var db = new ApplicationDbContext();
var riders = new List<ApplicationUser>();
foreach(RiderViewModel r in model.Riders)
{
var user = db.Users.FirstOrDefault(u => u.Id == r.Id);
if(user == null)
{
ModelState.AddModelError(string.Empty, "Er is een Fout opgetreden bij het selecteren van de leden. contacteer de systeembeheerder indien het probleem blijft bestaan");
return View(model);
}
riders.Add(user);
}
var ride = new Ride
{
Date = model.Date,
Punten = model.Punten,
Riders = riders
};
db.Rides.Add(ride);
db.SaveChanges();
return RedirectToAction("Index", "AdminPanel");
}
return View(model);
}
and this is the view:
using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Ride</h4>
<hr />
<div class="form-group">
@Html.LabelFor(model => model.Date, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Date, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Date, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Punten, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Punten, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Punten, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.Label("Leden", htmlAttributes: new { @class = "control-label col-md-2"})
<div class="col-md-10">
@for (var i = 0; i < Model.Riders.Count(); i++)
{
<div class="col-md-10">
@Html.HiddenFor(model => model.Riders[i])
@Html.CheckBoxFor(model => model.Riders[i].IsChecked)
@Html.LabelFor(model => model.Riders[i].IsChecked, Model.Riders[i].FulllName)
</div>
}
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
Thanx a lot.
grtz Jeff
Upvotes: 2
Views: 89
Reputation:
Your usage of
@Html.HiddenFor(model => model.Riders[i])
is creating a hidden input for a complex property which is typeof RiderViewModel
. If you inspect the html, it will be something like
<input type="hidden" id="Riders_0_" name="Riders[0]" value="someAssembly.RiderViewModel" />
When you submit, the DefaultModelBinder
tries to set model.Riders[0]
to the value someAssembly.RiderViewModel
which fails and so model.Riders[0]
is null
Assuming you want to generate a hidden input for the ID property, change it to
@Html.HiddenFor(model => model.Riders[i].ID)
Upvotes: 1
Reputation: 481
You can use a EditorTemplate for this, just add a new file in the EditorTemplates folder named RiderViewModel :
@model RiderViewModel
<div class="col-md-10">
@Html.HiddenFor(model => model.Id)
@Html.CheckBoxFor(model => model.IsChecked)
@Html.LabelFor(model => model.IsChecked, Model.FulllName)
</div>
Then in the view just call the EditorFor:
@Html.EditorFor(m => m.Riders)
Upvotes: 1