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

本文的环境是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());


来表示二者的绑定关系。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值