问题
I am a bit lost here as I have not really looked at model binders so if possible, can one advise me if I am actually thinking about my problem correctly... :) and if my code is way of, please advise...
1 -I have a DTO class which contains 'custom fields' each with a name and other properties i.e.:
Public Class CustomFields
{
public string Name {get;set;}
public string Description {get;set;}
public string FieldType {get;set;}
public string Value {get;set;}
}
2- Within my repo/business layer I am setting the values and returning ICollection for the view to render
3- the view uses a foreach to display fields
<% foreach (var item in Model) {%>
<div class="editor-label">
<%= Html.Label(item.Name) %>
</div>
<div class="editor-field">
<%= Html.TextBox(item.Name, item.Value)%>
</div>
<% } %>
Question: What is the best way to retrieve the result via a post? If there are errors I need to send back the errors to the view...
NOTE: What I did-->
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index([ModelBinder(typeof(CustomModelBinder))] ICollection<CustomFields> Fields)
{
//code here...
}
Custom Model binder gets values from form collection and transforms in into the correct type- is this correct? The best way to do this? I get the feeling I overcomplicated things...
public class CustomModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
var fields = new List<CustomFields>();
var formCollection = new FormCollection(controllerContext.HttpContext.Request.Form);
foreach (string _key in formCollection)
{
if (_key.Contains("_RequestVerificationToken"))
break;
fields.Add(new CustomFields { Name = _key,
Value = formCollection.GetValue(_key).AttemptedValue });
}
return fields;
}
}
回答1:
Everything is perfect until step 3 where you mention foreach loops in a view. That's where I would stop and use editor templates instead. So replace the loop in your view by:
<%= Html.EditorForModel() %>
and inside the corresponding editor template which will be rendered for each element of the model collection (~/Views/Shared/EditorTemplates/CustomFields.ascx):
<div class="editor-label">
<%= Html.LabelFor(x => x.Name) %>
</div>
<div class="editor-field">
<%= Html.TextBoxFor(x => x.Name) %>
</div>
<div class="editor-field">
<%= Html.TextBoxFor(x => x.Value) %>
</div>
<div class="editor-field">
<%= Html.TextBoxFor(x => x.Description) %>
</div>
<div class="editor-field">
<%= Html.TextBoxFor(x => x.FieldType) %>
</div>
then simply:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(IEnumerable<CustomFields> fields)
{
//code here...
}
No need of any model binders. The editor template will take care of generating proper names for the input fields so that they are correctly bound.
来源:https://stackoverflow.com/questions/5513091/retrieving-data-from-view-should-i-use-model-binder