• 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());


    来表示二者的绑定关系。

  • 相关阅读:
    [LeetCode] Insert Interval
    java 可变參数
    谈谈单元測试之(二):測试工具 JUnit 3
    我的csdn博客搬家了
    leetcode 229: Majority Element II
    向MapReduce转换:生成用户向量
    《31天成为IT服务达人》最新文件夹
    SD卡读写之FileNotFoundException: /storage/emulated/0object.txt: open failed: ENOENT (No such file or dir
    当写烂代码的人离职之后....
    JavaSE Map的使用
  • 原文地址:https://www.cnblogs.com/cxd4321/p/1572774.html
Copyright © 2020-2023  润新知