UpdateModel with Dictionary/Hashtable
I'm trying out some MVC stuff and I was wondering if there's some way to edit dynamic fields. So to try this I added a keyed collection called CustomFields. I've tried both Hashtable and Dictionary.
In the view I then wrote:
<%:Html.TextBoxFor(model => model.CustomFields["x"])%>
This then generated this HTML:
<input id="CustomFields_x_" name="CustomFields[x]" ty开发者_StackOverflow社区pe="text" value="" />
So it looks like I'm on the right way and that there are some functionality for this. But the problem is that when I call UpdateModel, it will not bind the value I write to this keyed collection.
Is this even possible to do? Do I need to do something special to solve it?
I'm fairly certain there's a built in way of handling this but I couldn't find it. However, you can accomplish what you want with the following IModelBinder implementation.
Create a custom Binder for your model. First we're going to use the default Model Binder to attach any properties that aren't your dictionary.
public class CustomFieldsModelBinder : IModelBinder {
IDictionary<string, string> dictionary;
public CustomFieldsModelBinder() { }
public object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext) {
if (bindingContext == null)
throw new ArgumentNullException("bindingContext");
CustomFieldsModel returnValue;
returnValue = (CustomFieldsModel)ModelBinders.Binders.DefaultBinder.BindModel(
controllerContext,
bindingContext);
if (returnValue == null) {
returnValue = new CustomFieldsModel();
}
if (returnValue.CustomFields == null)
returnValue.CustomFields = new Dictionary<string, string>();
foreach (string name in DictionaryKeyNames(controllerContext, "CustomFields")) {
var postValue = controllerContext.HttpContext.Request.Form["CustomFields[" + name + "]"];
returnValue.CustomFields[name] = postValue;
}
return returnValue;
}
//this method will grab the [name]'s from the collection
protected virtual IList<string> DictionaryKeyNames(ControllerContext context, string prefix) {
IList<string> list = new List<string>();
Regex pattern = new Regex("^" + prefix + @"\[([^\]]+)\]");
foreach (var key in context.HttpContext.Request.Form.AllKeys) {
var match = pattern.Match(key);
if (match.Success && !list.Contains(match.Value)) {
list.Add(match.Groups[1].Value);
}
}
return list;
}
}
Once you have that you can then register your binder in the Global.asax
ModelBinders.Binders[typeof(CustomFieldsModel)] = new CustomFieldsModelBinder() { };
精彩评论