问题
I have a scenario I'm stuck on - I have a domain object that has a collection of objects attached to it. Something like this:
public class Person
{
public string Name { get; set; }
public IList<PhoneNumber> PhoneNumbers {get; set; }
public IList<Address> Addresses { get; set; }
}
The UI the client wants has a single input form for adding and editing. A user could enter 0 to many phones/addresses for each person. How do I handle posting the collection of values back to the controller?
I can think of a couple of approaches, but they all seem brute-force and not very elegant. Is there a best practice for handling this sort of problem?
回答1:
It is supported by the framework by using a special "form layout". Phil Haack has an article on this, check this out
Edit Scott Hanselman (http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx) just posted an update on this. Furthermore in RC1 it seems (ran into this mysel last night) that the indexes needs to be 0-based and steadily increasing (at least if you are "binding" against IList)
Edit2 Link didn't seem to work
回答2:
In the past I've used the railsy convention for this.
<input name="Parent[childObjectType][serial_number]" type="textbox" value="" />
So for your situation this
<input name="Person[PhoneNumber][1]" type="TextBox" value="555-1212" />
<input name="Person[PhoneNumber][2]" type="TextBox" value="555-555-1212" />
and you can increment the serial number and replicate the element in javascript to get multiple, and use a formCollection in your action which will give you a way to get these elements.
The default from the mvc team is to used a ModelBinder, and dot syntax for this operation. However this makes jquery and other javascript frameworks baulk.
回答3:
I have been starting to use json and jQuery to post complex types to a controller action using JSON.NET and a JsonFilter on the server side which automatically takes your json object and serializes it to the equivalent C# type. I have found this to be a very clean solution and easier to test. You can check out this post with the sample code to download to get you started on how to do it. It is pretty straight forward.
http://blogger.forgottenskies.com/?p=252
回答4:
In mentioned Hanselman's post he writes that you don't need indexes, you just have the same name for input boxes and have a array parameter in action and it works.
回答5:
I've done this several times and have used Phil Haack's post as a guide. This last time I figured out how to make it work with Editor Templates. Posting this here in hopes it helps someone else down the road (or me if I ever forget).
My example here is using Addresses (using only one property out for brevity).
AddressViewModel.cs
public class AddressViewModel
{
public string Address1 { get; set; }
}
AddressViewModels.cs
public class AddressViewModels : List<AddressViewModel>
{
}
PersonViewModel.cs
public class PersonViewModel
{
public AddressViewModels HomeAddresses { get; set; }
}
AddressViewModel.cshtml (Editor Template)
@model AddressViewModel
<div>
@Html.LabelFor(m => m.Address1)
@Html.TextBoxFor(m => m.Address1)
</div>
AddressViewModels.cshtml (Editor Template)
@model AddressViewModels
@for (var i = 0; i < Model.Count; i++)
{
@Html.Hidden("Index", i)
@Html.EditorFor(m => Model[i])
}
Person.cshtml
@model Person
<h3>Edit Addresses</h3>
@Html.EditorFor(m => m.HomeAddresses)
<button type="submit">Save</button>
Rendered HTML
<input id="HomeAddresses_Index" name="HomeAddresses.Index" type="hidden" value="0">
<label for="HomeAddresses_1__Address1">Address 1</label>
<input id="HomeAddresses_1__Address1" name="HomeAddresses[1].Address1" type="text" value="P.O.Box 123" >
<button type="submit">Save</button>
来源:https://stackoverflow.com/questions/542389/asp-net-mvc-handling-multiple-objects-in-one-form