在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
本文的环境是Asp.net Mvc Codeplex Preview 5
前文提到我们可以使用 Controller中的UpdateModel来获取 繁杂类型 例如
1 UpdateModel(x, Request.Form.AllKeys);
但是这里有些问题,当我们使用Request.Form.AllKeys时,提交的数据中有非x属性时,就会发生错误: The model of type 'MyModel' does not have a property named 'Name2'. 但是使用
1 UpdateModel(x, new[] {"IDX", "Name"});
这种形式,我们又会觉得它太过麻烦。
其实Asp.net Mvc为我们提供了一种很简单的传递复杂数据的方式,它类似于Monorail中的DataBinder: 我们完全可以通过以下方式来传递数据。例如 view:
1 <%using (Html.Form("home", "about", FormMethod.Post)) {%>
2 <%=Html.TextBox("my.ID")%> 3 <%=Html.TextBox("my.Name")%> 4 <%=Html.SubmitButton()%> 5 <%} %> controller:
[AcceptVerbs("post")]
public ActionResult About([ModelBinder(typeof(MyModelBinder))]MyModel my) { ViewData["Title"] =my.Name + my.ID; return View(); } 这样我们就可以从my中获取到Post过来的值了,这里的关键在于[ModelBinder(typeof(MyModelBinder))]
而 MyModelBinder的实现方法如下
1 using System;
2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Globalization; 5 using System.Linq; 6 using System.Web.Mvc; 7 8 /// <summary> 9 /// 这个类是根据Controller.UpdateModel方法更改而成 10 /// </summary> 11 public class MyModelBinder : IModelBinder{ 12 #region IModelBinder 成员 13 14 public object GetValue(ControllerContext controllerContext, string modelName, Type modelType, 15 ModelStateDictionary modelState){ 16 object model = Activator.CreateInstance(modelType); //将做为参数的类实例化了 17 IEnumerable<string> keys = modelType.GetProperties().Select(c => c.Name); //得到该对象的属性的名的字符串数组,这里的结果应该为["ID","Name"] 18 string objectPrefix = modelName; //这个就是,我的对象名叫my则会检查 name="my.ID" name="my.Name"的表单字段 19 20 PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(model); //对象的属性的集合 21 var dictionary = new Dictionary<string, PropertyDescriptor>(); 22 foreach (string str in keys){ 23 //遍历属性的字符串集合即["ID","Name"] 24 if (!string.IsNullOrEmpty(str)){ 25 PropertyDescriptor descriptor = properties.Find(str, true); 26 if (descriptor == null){ 27 throw new ArgumentException( 28 string.Format(CultureInfo.CurrentUICulture, "无此属性{0},{1}", new object[]{model.GetType().FullName, str}), 29 "modelName"); 30 } 31 string str3 = string.IsNullOrEmpty(objectPrefix) ? str : (objectPrefix + "." + str); //将对象名与属性名拼接,如my.ID 32 dictionary[str3] = descriptor; 33 } 34 } 35 foreach (var pair in dictionary){ 36 string key = pair.Key; 37 PropertyDescriptor descriptor2 = pair.Value; 38 object obj2 = ModelBinders.GetBinder(descriptor2.PropertyType).GetValue(controllerContext, key, 39 descriptor2.PropertyType, modelState); 40 if (obj2 != null){ 41 try{ 42 descriptor2.SetValue(model, obj2); //设置属性的值 43 continue; 44 } 45 catch{ 46 //如果有使用验证Helepr则会显示在Html.ValidationSummary中 47 string errorMessage = string.Format(CultureInfo.CurrentCulture, "验证失败{0}:{1}", new[]{obj2, descriptor2.Name}); 48 string attemptedValue = Convert.ToString(obj2, CultureInfo.CurrentCulture); 49 modelState.AddModelError(key, attemptedValue, errorMessage); 50 continue; 51 } 52 } 53 } 54 return model; //最后 返回这个我们设置完属性的对象 55 } 56 57 #endregion 58 }
这样我们就实现了 用Action的参数传递复杂类型。
当然,如果你连[ModelBinder(typeof(MyModelBinder))]都不想写了,想直接来以下写法,
1 [AcceptVerbs("post")]
2 public ActionResult About(MyModel my) { 3 ViewData["Title"] =my.Name + my.ID; 4 return View(); 5 }
这个也是可以的不过你要在Application_Start中添加 ModelBinders.Binders.Add(typeof (MyModel), new MyModelBinder()); 来表示二者的绑定关系。 |
请发表评论