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

简介: 本文的环境是Asp.net Mvc Codeplex Preview 5   前文提到我们可以使用 Controller中的UpdateModel来获取 繁杂类型 例如 1 UpdateModel(x, Request.

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


来表示二者的绑定关系。

 

多谢Leven's Bloglulu Studio

 

 

示例程序下载http://files.cnblogs.com/chsword/MyModelBinder.rar

 

目录
相关文章
|
JSON 前端开发 Java
Spring MVC入门必读:注解、参数传递、返回值和页面跳转(下)
Spring MVC入门必读:注解、参数传递、返回值和页面跳转(下)
128 0
|
7月前
|
存储 C#
揭秘C#.Net编程秘宝:结构体类型Struct,让你的数据结构秒变高效战斗机,编程界的新星就是你!
【8月更文挑战第4天】在C#编程中,结构体(`struct`)是一种整合多种数据类型的复合数据类型。与类不同,结构体是值类型,意味着数据被直接复制而非引用。这使其适合表示小型、固定的数据结构如点坐标。结构体默认私有成员且不可变,除非明确指定。通过`struct`关键字定义,可以包含字段、构造函数及方法。例如,定义一个表示二维点的结构体,并实现计算距离原点的方法。使用时如同普通类型,可通过实例化并调用其成员。设计时推荐保持结构体不可变以避免副作用,并注意装箱拆箱可能导致的性能影响。掌握结构体有助于构建高效的应用程序。
224 7
|
10月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
267 0
|
7月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
93 0
|
10月前
|
安全 API C#
C#.Net筑基-类型系统②常见类型--枚举Enum
枚举(enum)是C#中的一种值类型,用于创建一组命名的整数常量。它们基于整数类型(如int、byte等),默认为int。枚举成员可指定值,未指定则从0开始自动递增。默认值为0。枚举可以与整数类型互相转换,并可通过`[Flags]`特性表示位域,支持位操作,用于多选场景。`System.Enum`类提供了如`HasFlag`、`GetName`等方法进行枚举操作。
122 7
|
10月前
|
编译器 C#
C#.Net筑基-类型系统②常见类型 --record是什么类型?
`record`在C#中是一种创建简单、只读数据结构的方式,常用于轻量级数据传输。它本质上是类(默认)或结构体的快捷形式,包含自动生成的属性、`Equals`、`ToString`、解构赋值等方法。记录类型可以继承其他record或接口,但不继承普通类。支持使用`with`语句创建副本。例如,`public record User(string Name, int Age)`会被编译为包含属性、相等比较和`ToString()`等方法的类。记录类型提供了解构赋值和自定义实现,如密封的`sealed`记录,防止子类重写。
|
10月前
|
存储 C#
C#.Net筑基-类型系统②常见类型--结构体类型Struct
本文介绍了C#中的结构体(struct)是一种用户自定义的值类型,适用于定义简单数据结构。结构体可以有构造函数,能定义字段、属性和方法,但不能有终结器或继承其他类。它们在栈上分配,参数传递为值传递,但在类成员或包含引用类型字段时例外。文章还提到了`readonly struct`和`ref struct`,前者要求所有字段为只读,后者强制结构体存储在栈上,适用于高性能场景,如Span和ReadOnlySpan。
|
8月前
|
开发框架 .NET API
.NET Core 和 .NET 标准类库项目类型有什么区别?
在 Visual Studio 中,可创建三种类库:.NET Framework、.NET Standard 和 .NET Core。.NET Standard 是规范,确保跨.NET实现的API一致性,适用于代码共享。.NET Framework 用于特定技术,如旧版支持。.NET Core 库允许访问更多API但限制兼容性。选择取决于兼容性和所需API:需要广泛兼容性时用.NET Standard,需要更多API时用.NET Core。.NET Standard 替代了 PCL,促进多平台共享代码。
|
10月前
|
存储 安全 Unix
C#.Net筑基-类型系统②常见类型--日期和时间的故事
在System命名空间中,有几种表示日期时间的不可变结构体(Struct):DateTime、DateTimeOffset、TimeSpan、DateOnly和TimeOnly。DateTime包含当前本地或UTC时间,以及最小和最大值;DateTimeOffset增加了时区偏移信息,适合跨时区操作。UTC是世界标准时间,而格林尼治标准时间(GMT)不稳定,已被更精确的UTC取代。DateTimeOffset和DateTime提供了转换为UTC和本地时间的方法,以及各种解析和格式化函数。
|
9月前
|
存储 编译器
【.NET Core】可为null类型详解
【.NET Core】可为null类型详解
255 0