My web application has a many-to-many link between the Station
and Timetable
entities, and the entity that links them is called StationTimetable
, which also holds data about the linkage between the two entities. When I create a new Timetable
, I want to create new (and multiple) StationTimetable
entries in the database to correspond to this new Timetable
.
So far I've managed to get the application to save just one StationTimetable
entry when the user creates a new timetable. I sort of understand why this is, and I've attempted to modify it to save multiple entries however I'm now hitting a brick wall in my knowledge.
So, I have a TimetablesCreateViewModel
which is the model my view uses:
public class TimetablesCreateViewModel
{
public Timetable Timetable { get; set; }
public IEnumerable<StationTimetable> StationTimetables { get; set; }
public Station Station { get; set; }
public SelectList StationList { get; set; }
}
In my view, I'm letting the user insert up to 10 StationTimetable
entries:
@for (var i = 0; i < 10; i++)
{
<tr>
<td>@Html.DropDownListFor(model => model.StationTimetables.StationId, Model.StationList, "---", htmlAttributes: new { @class = "form-control col-md-2" })</td>
<td>@Html.EditorFor(model => model.StationTimetables.Arrival, new { htmlAttributes = new { @class = "form-control" } })</td>
<td>@Html.EditorFor(model => model.StationTimetables.Departure, new { htmlAttributes = new { @class = "form-control" } })</td>
</tr>
}
And then, in my controller method, I want to do something like the following:
public ActionResult Create(TimetablesCreateViewModel viewModel)
{
if (ModelState.IsValid)
{
db.Timetables.Add(viewModel.Timetable);
// Somehow loop over viewModel.StationTimetables and add them here?
// db.StationTimetables.Add(viewModel.StationTimetable);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(viewModel);
}
The immediate problem seems to be that the DropDownListFor
and EditorFor
methods in my view are complaining, and that makes sense as I've specified StationTimetables
in my view model to be IEnumerable
, and I can't access the StationId
, Arrival
and Departure
properties of IEnumerable
. Those properties are part of the entity that IEnumerable
holds.
Unfortunately, I don't know how to use the Html
helper to create a form where I can populate StationTimetables
with a number of StationTimetable
entities. If I could just get multiple StationTimetable
entries to my Create
method, I don't think I'll have a problem adding them to the database after that.
Thank you for any help.
You need to make your StationTimetables
property IList
and use the indexer so that the properties are correctly named and can be bound on post back
@for (var i = 0; i < 10; i++)
{
<tr>
<td>@Html.DropDownListFor(m => m.StationTimetables[i].StationId, Model.StationList, "---", htmlAttributes: new { @class = "form-control col-md-2" })</td>
<td>@Html.EditorFor(m => m.StationTimetables[i].Arrival, new { htmlAttributes = new { @class = "form-control" } })</td>
<td>@Html.EditorFor(m => m.StationTimetables[i].Departure, new { htmlAttributes = new { @class = "form-control" } })</td>
</tr>
}
This will generate the correct name attributes for example
<input name="StationTimetables[0].StationId" ...>
<input name="StationTimetables[1].StationId" ...>
If you cant change it from IEnumerable
, you can create a custom EditorTemplate
for typeof StationTimetable
Views/Shared/EditorTemplates/StationTimetable.cshtml
@model YourAssembly.StationTimetable
<tr>
<td>@Html.DropDownListFor(m => m.StationId, (SelectList)ViewData["StationList"], "---", new { @class = "form-control col-md-2" })</td>
<td>@Html.EditorFor(m => m.Arrival, new { htmlAttributes = new { @class = "form-control" } })</td>
<td>@Html.EditorFor(m => m.Departure, new { htmlAttributes = new { @class = "form-control" } })</td>
</tr>
and then in the main view
@EditorFor(m => m.StationTimetables, new { StationList = Model.Model.StationList })
This approach means you need to initialize the StationTimetables
property with 10 items in the controller before you pass the model to the view.
In any case, I recommend the EditorFor()
approach in your case because of a bug (reported but not yet solved) in using DropDownListFor()
in a for
loop.
However I suspect you don't really always have exactly 10 station timetables (I'm letting the user insert up to 10) which makes this approach inflexible - for example if you add validation attributes to the properties, the model will be invalid unless all 10 time table properties are filled in. It would be better to use javascript or the BeginCollectionItem helper to dynamically add a new timetable. A example of both approaches is included in this answer
来源:https://stackoverflow.com/questions/28047465/inserting-multiple-entities-into-many-to-many-linking-table