首页 > 代码库 > asp.net MVC 4.0 Controller回顾——ModelBinding过程
asp.net MVC 4.0 Controller回顾——ModelBinding过程
以DefaultModelBinder为例
为简单模型绑定(BindSimpleModel)和复杂模型绑定(BindSimpleModel)
1 public virtual object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 2 { 3 if (bindingContext == null) 4 { 5 throw new ArgumentNullException("bindingContext"); 6 } 7 bool flag = false; 8 if (!string.IsNullOrEmpty(bindingContext.ModelName) && !bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName)) 9 {10 .......11 }12 if (!flag)13 {14 .......15 if (valueProviderResult != null)16 {17 return this.BindSimpleModel(controllerContext, bindingContext, valueProviderResult);18 }19 }20 if (!bindingContext.ModelMetadata.IsComplexType)21 {22 return null;23 }24 return this.BindComplexModel(controllerContext, bindingContext);25 }
复杂类型 |
绑定类型为复杂类型是绑定属性
internal void BindComplexElementalModel(ControllerContext controllerContext, ModelBindingContext bindingContext, object model) { ModelBindingContext context = this.CreateComplexElementalModelBindingContext(controllerContext, bindingContext, model); if (this.OnModelUpdating(controllerContext, context)) { this.BindProperties(controllerContext, context); this.OnModelUpdated(controllerContext, context); } }
遍历属性描述进行绑定
1 private void BindProperties(ControllerContext controllerContext, ModelBindingContext bindingContext)2 {3 foreach (PropertyDescriptor descriptor in this.GetFilteredModelProperties(controllerContext, bindingContext))4 {5 this.BindProperty(controllerContext, bindingContext, descriptor);6 }7 }
这时又会把bindingContext.ModelName和propertyDescriptor.Name进行组合成为新的前缀进行值得获取,并且获取新的ModelBindingContext进行绑定
1 protected virtual void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor) 2 { 3 string prefix = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name); 4 if (bindingContext.ValueProvider.ContainsPrefix(prefix)) 5 { 6 IModelBinder propertyBinder = this.Binders.GetBinder(propertyDescriptor.PropertyType); 7 object obj2 = propertyDescriptor.GetValue(bindingContext.Model); 8 ModelMetadata metadata =http://www.mamicode.com/ bindingContext.PropertyMetadata[propertyDescriptor.Name]; 9 metadata.Model = obj2;10 ModelBindingContext context = new ModelBindingContext {11 ModelMetadata =http://www.mamicode.com/ metadata,12 ModelName = prefix,13 ModelState = bindingContext.ModelState,14 ValueProvider = bindingContext.ValueProvider15 };16 object obj3 = this.GetPropertyValue(controllerContext, context, propertyDescriptor, propertyBinder);17 ......18 }
集合类型、数组类型 |
1 internal object BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 2 { 3 ...... 4 Type type7 = TypeHelpers.ExtractGenericInterface(modelType, typeof(IEnumerable<>)); 5 if (type7 != null) 6 { 7 Type type8 = type7.GetGenericArguments()[0]; 8 if (typeof(ICollection<>).MakeGenericType(new Type[] { type8 }).IsInstanceOfType(model)) 9 {10 ModelBindingContext context6 = new ModelBindingContext();11 if (func2 == null)12 {13 func2 = () => model;14 }15 context6.ModelMetadata =http://www.mamicode.com/ ModelMetadataProviders.Current.GetMetadataForType(func2, modelType);16 context6.ModelName = bindingContext.ModelName;17 context6.ModelState = bindingContext.ModelState;18 context6.PropertyFilter = bindingContext.PropertyFilter;19 context6.ValueProvider = bindingContext.ValueProvider;20 ModelBindingContext context5 = context6;21 return this.UpdateCollection(controllerContext, context5, type8);22 }23 }24 ......25 }
GetIndexes()获取Name=Index的IEnumerable<string>集合(字符串索引集合),再根据ModelName+[当前索引前缀],进行模型绑定,通过ValueProvider.ContainsPrefix(prefix)判断是否包含当前前缀的,重新获取elementType的ModelBindingContext进行模型绑定(elementType为集合类型,通过 type7.GetGenericArguments()[0]获取到)
internal object UpdateCollection(ControllerContext controllerContext, ModelBindingContext bindingContext, Type elementType) { bool flag; IEnumerable<string> enumerable; GetIndexes(bindingContext, out flag, out enumerable); IModelBinder binder = this.Binders.GetBinder(elementType); List<object> newContents = new List<object>(); foreach (string str in enumerable) { string prefix = CreateSubIndexName(bindingContext.ModelName, str); if (!bindingContext.ValueProvider.ContainsPrefix(prefix)) { if (!flag) { continue; } break; } ModelBindingContext context = new ModelBindingContext { ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, elementType), ModelName = prefix, ModelState = bindingContext.ModelState, PropertyFilter = bindingContext.PropertyFilter, ValueProvider = bindingContext.ValueProvider }; object obj2 = binder.BindModel(controllerContext, context); AddValueRequiredMessageToModelState(controllerContext, bindingContext.ModelState, prefix, elementType, obj2); newContents.Add(obj2); } if (newContents.Count == 0) { return null; } object model = bindingContext.Model; CollectionHelpers.ReplaceCollection(elementType, model, newContents); return model; }
View代码
1 @using System.Collections.ObjectModel 2 @model ObservableCollection<MvcSource.Models.LogOnModel> 3 4 @Html.LabelFor(m => m[0].UserName) 5 @Html.LabelFor(m => m[0].Password) 6 @Html.CheckBoxFor(m => m[0].RememberMe) 7 8 @Html.LabelFor(m => m[1].UserName) 9 @Html.LabelFor(m => m[1].Password)10 @Html.CheckBoxFor(m => m[1].RememberMe)
生成出来的HTML源码
1 <input name="[0].UserName" type="text" value=http://www.mamicode.com/"" />2 <input name="[0].Password" type="password" />3 <input name="[0].RememberMe" type="checkbox" value=http://www.mamicode.com/"true" />4 5 <input name="[1].UserName" type="text" value=http://www.mamicode.com/"" />6 <input name="[1].Password" type="password" />7 <input name="[1].RememberMe" type="checkbox" value=http://www.mamicode.com/"true" />
Controller调用方法参数为List<T>
1 [HttpPost]2 public ActionResult LogOn(List<LogOnModel> UserName)3 {4 return View();5 }
上面分析UpdateCollection 时这时候模型绑定的前缀为 [0].UserName
NameValueCollectionValueProvider类获取key值
asp.net MVC 4.0 Controller回顾——ModelBinding过程
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。