点击这里给我发消息 点击这里给我发消息

Asp.net Mvc Codeplex Preview 5 第三篇 实现Action参数传递繁杂类型

添加时间:2010-1-5
    相关阅读: 程序

示例程序下载:http://file.ddvip.com/2008_10/1225161106_ddvip_7144.rar

  本文的环境是Asp.net Mvc Codeplex Preview 5

  前文提到我们可以使用 Controller中的UpdateModel来获取 繁杂类型

  例如

  1 UpdateModel(x,Request.Form.AllKeys);

  但是这里有些问题,当我们使用Request.Form.AllKeys时,提交的数据中有非x属性时,就会发生错误:

  Themodeloftype'MyModel'doesnothaveapropertynamed'Name2'.

  但是使用

  1UpdateModel(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")]
    publicActionResultAbout([ModelBinder(typeof(MyModelBinder))]MyModelmy){
      ViewData["Title"]=my.Name+my.ID;
      returnView();
    }

  这样我们就可以从my中获取到Post过来的值了,这里的关键在于[ModelBinder(typeof(MyModelBinder))]

 而 MyModelBinder的实现方法如下

1usingSystem;
2usingSystem.Collections.Generic;
3usingSystem.ComponentModel;
4usingSystem.Globalization;
5usingSystem.Linq;
6usingSystem.Web.Mvc;
7
8///<summary>
9///这个类是根据Controller.UpdateModel方法更改而成
10///</summary>
11publicclassMyModelBinder:IModelBinder{
12  #regionIModelBinder成员
13
14  publicobjectGetValue(ControllerContextcontrollerContext,stringmodelName,TypemodelType,
15              ModelStateDictionarymodelState){
16    objectmodel=Activator.CreateInstance(modelType);//将做为参数的类实例化了
17    IEnumerable<string>keys=modelType.GetProperties().Select(c=>c.Name);//得到该对象的属性的名的字符串数组,这里的结果应该为["ID","Name"]
18    stringobjectPrefix=modelName;//这个就是,我的对象名叫my则会检查 name="my.ID"name="my.Name"的表单字段
19
20    PropertyDescriptorCollectionproperties=TypeDescriptor.GetProperties(model);//对象的属性的集合
21    vardictionary=newDictionary<string,PropertyDescriptor>();
22    foreach(stringstrinkeys){
23//遍历属性的字符串集合即["ID","Name"]
24      if(!string.IsNullOrEmpty(str)){
25        PropertyDescriptordescriptor=properties.Find(str,true);
26        if(descriptor==null){
27          thrownewArgumentException(
28            string.Format(CultureInfo.CurrentUICulture,"无此属性{0},{1}",newobject[]{model.GetType().FullName,str}),
29            "modelName");
30        }
31        stringstr3=string.IsNullOrEmpty(objectPrefix)?str:(objectPrefix+"."+str);//将对象名与属性名拼接,如my.ID
32        dictionary[str3]=descriptor;
33      }
34    }
35    foreach(varpairindictionary){
36      stringkey=pair.Key;
37      PropertyDescriptordescriptor2=pair.Value;
38      objectobj2=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          stringerrorMessage=string.Format(CultureInfo.CurrentCulture,"验证失败{0}:{1}",new[]{obj2,descriptor2.Name});
48          stringattemptedValue=Convert.ToString(obj2,CultureInfo.CurrentCulture);
49          modelState.AddModelError(key,attemptedValue,errorMessage);
50          continue;
51        }
52      }
53    }
54    returnmodel;//最后返回这个我们设置完属性的对象
55  }
56
57  #endregion
58}


  这样我们就实现了 用Action的参数传递复杂类型。

  当然,如果你连[ModelBinder(typeof(MyModelBinder))]都不想写了,想直接来以下写法,

1    [AcceptVerbs("post")]
2    publicActionResultAbout(MyModelmy){
3      ViewData["Title"]=my.Name+my.ID;
4      returnView();
5    }

  这个也是可以的不过你要在Application_Start中添加

  ModelBinders.Binders.Add(typeof (MyModel), new MyModelBinder());

  来表示二者的绑定关系

本文作者:
咨询热线:020-85648757 85648755 85648616 0755-27912581 客服:020-85648756 0755-27912581 业务传真:020-32579052
广州市网景网络科技有限公司 Copyright◎2003-2008 Veelink.com. All Rights Reserved.
广州商务地址:广东省广州市黄埔大道中203号(海景园区)海景花园C栋501室
= 深圳商务地址:深圳市宝源路华丰宝源大厦606
研发中心:广东广州市天河软件园海景园区 粤ICP备05103322号 工商注册