首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> 關於ASP.NET

ASP.NET MVC Codeplex Preview 5 實戰(三):Action 參數綁定複雜類型的最佳實踐

     編輯:關於ASP.NET

環境:ASP.NET MVC Codeplex Preview 5。

問題:UpdateModel 的侷限性

  • UpdateModel(x, Request.Form.AllKeys):表單含非模型欄位會報錯(The model of type 'MyModel' does not have a property named 'Name2')。
  • UpdateModel(x, new[] {"IDX","Name"}):需逐一列出欄位,繁瑣。

解決方案:ModelBinder 屬性 + 前綴命名

View: 表單欄位加前綴 my.

<%using (Html.Form("home","about",FormMethod.Post)){%>
  <%=Html.TextBox("my.ID")%>
  <%=Html.TextBox("my.Name")%>
  <%=Html.SubmitButton()%>
<%}%>

Controller: 參數標註 [ModelBinder(typeof(MyModelBinder))]。

[AcceptVerbs("post")]
public ActionResult About([ModelBinder(typeof(MyModelBinder))] MyModel my) {
  ViewData["Title"] = my.Name + my.ID;
  return View();
}

自訂 ModelBinder 實作

關鍵邏輯:反射取得模型屬性,組合 前綴.屬性名 匹配表單欄位,逐一綁定並處理驗證錯誤。

public class MyModelBinder : IModelBinder {
  public object GetValue(ControllerContext controllerContext, string modelName, Type modelType, ModelStateDictionary modelState) {
    object model = Activator.CreateInstance(modelType);
    var keys = modelType.GetProperties().Select(c => c.Name);
    string objectPrefix = modelName; // "my"
    var properties = TypeDescriptor.GetProperties(model);
    var dictionary = new Dictionary<string, PropertyDescriptor>();

    foreach (string str in keys) {
      if (!string.IsNullOrEmpty(str)) {
        var descriptor = properties.Find(str, true);
        if (descriptor == null) throw new ArgumentException(...);
        string str3 = string.IsNullOrEmpty(objectPrefix) ? str : (objectPrefix + "." + str); // "my.ID"
        dictionary[str3] = descriptor;
      }
    }

    foreach (var pair in dictionary) {
      string key = pair.Key;
      var descriptor2 = pair.Value;
      object obj2 = ModelBinders.GetBinder(descriptor2.PropertyType).GetValue(controllerContext, key, descriptor2.PropertyType, modelState);
      if (obj2 != null) {
        try { descriptor2.SetValue(model, obj2); continue; }
        catch {
          modelState.AddModelError(key, Convert.ToString(obj2), "驗證失敗...");
        }
      }
    }
    return model;
  }
}

進階:全域註冊免標註

在 Application_Start 註冊:ModelBinders.Binders.Add(typeof(MyModel), new MyModelBinder());,Action 參數即可直接寫 MyModel my 無需屬性標註。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved