zoukankan      html  css  js  c++  java
  • 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());


    来表示二者的绑定关系。

    多谢Leven's Bloglulu Studio

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

  • 相关阅读:
    leetcode 309. Best Time to Buy and Sell Stock with Cooldown
    leetcode 714. Best Time to Buy and Sell Stock with Transaction Fee
    leetcode 32. Longest Valid Parentheses
    leetcode 224. Basic Calculator
    leetcode 540. Single Element in a Sorted Array
    leetcode 109. Convert Sorted List to Binary Search Tree
    leetcode 3. Longest Substring Without Repeating Characters
    leetcode 84. Largest Rectangle in Histogram
    leetcode 338. Counting Bits
    git教程之回到过去,版本对比
  • 原文地址:https://www.cnblogs.com/cxd4321/p/1567904.html
Copyright © 2011-2022 走看看