2013-08-16 68 views
2

我見過很多類似的帖子,但沒有找到控制器parameters特有的答案。模型綁定時獲取參數的自定義屬性

我寫了一個名爲AliasAttribute的自定義屬性,它允許我在模型綁定過程中爲參數定義別名。因此,舉例來說,如果我有:public JsonResult EmailCheck(string email)在服務器上,我想email參數綁定到一個名爲PrimaryEmailSomeCrazyEmail我可以「地圖」這一領域使用aliasattribute這樣的:public JsonResult EmailCheck([Alias(Suffix = "Email")]string email)

問題:在我的自定義模型綁定我不能應用到email參數AliasAttribute類的保持。它總是返回null。 我已經看到了什麼樣的DefaultModelBinder類正在做的反射器中獲得BindAttribute和它的相同,但不適用於我。

問題:如何在綁定過程中獲得此屬性?

AliasModelBinder:

public class AliasModelBinder : DefaultModelBinder 
{ 
    public static ICustomTypeDescriptor GetTypeDescriptor(Type type) 
    { 
     return new AssociatedMetadataTypeTypeDescriptionProvider(type).GetTypeDescriptor(type); 
    } 

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     var value = base.BindModel(controllerContext, bindingContext); 

     var descriptor = GetTypeDescriptor(bindingContext.ModelType); 
     /*************************/ 
     // this next statement returns null! 
     /*************************/ 
     AliasAttribute attr = (AliasAttribute)descriptor.GetAttributes()[typeof(AliasAttribute)]; 

     if (attr == null) 
      return null; 

     HttpRequestBase request = controllerContext.HttpContext.Request; 

     foreach (var key in request.Form.AllKeys) 
     { 
      if (string.IsNullOrEmpty(attr.Prefix) == false) 
      { 
       if (key.StartsWith(attr.Prefix, StringComparison.InvariantCultureIgnoreCase)) 
       { 
        if (string.IsNullOrEmpty(attr.Suffix) == false) 
        { 
         if (key.EndsWith(attr.Suffix, StringComparison.InvariantCultureIgnoreCase)) 
         { 
          return request.Form.Get(key); 
         } 
        } 
        return request.Form.Get(key); 
       } 
      } 
      else if (string.IsNullOrEmpty(attr.Suffix) == false) 
      { 
       if (key.EndsWith(attr.Suffix, StringComparison.InvariantCultureIgnoreCase)) 
       { 
        return request.Form.Get(key); 
       } 
      } 
      if (attr.HasIncludes) 
      { 
       foreach (var include in attr.InlcludeSplit) 
       { 
        if (key.Equals(include, StringComparison.InvariantCultureIgnoreCase)) 
        { 
         return request.Form.Get(include); 
        } 
       } 
      } 
     } 
     return null; 
    } 
} 

AliasAttribute:

[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Class, AllowMultiple = false, Inherited = true)] 
public class AliasAttribute : Attribute 
{ 
    private string _include; 
    private string[] _inlcludeSplit = new string[0]; 

    public string Prefix { get; set; } 
    public string Suffix { get; set; } 
    public string Include 
    { 
     get 
     { 
      return _include; 
     } 
     set 
     { 
      _include = value; 
      _inlcludeSplit = SplitString(_include); 
     } 
    } 
    public string[] InlcludeSplit 
    { 
     get 
     { 
      return _inlcludeSplit; 
     } 
    } 
    public bool HasIncludes { get { return InlcludeSplit.Length > 0; } } 


    internal static string[] SplitString(string original) 
    { 
     if (string.IsNullOrEmpty(original)) 
     { 
      return new string[0]; 
     } 
     return (from piece in original.Split(new char[] { ',' }) 
       let trimmed = piece.Trim() 
       where !string.IsNullOrEmpty(trimmed) 
       select trimmed).ToArray<string>(); 
    } 
} 

用法:

public JsonResult EmailCheck([ModelBinder(typeof(AliasModelBinder)), Alias(Suffix = "Email")]string email) 
{ 
    // email will be assigned to any field suffixed with "Email". e.g. PrimaryEmail, SecondaryEmail and so on 
} 

回答

0

放棄了這個,然後跨過Action Parameter Alias代碼庫,可能會允許我這樣做絆倒這個。它不像我開始寫的那樣靈活,但可能會被修改爲允許通配符。

0

我所做的就是讓我的屬性子類System.Web.Mvc.CustomModelBinderAttribute,然後它允許您返回您的自定義模型綁定的版本與別名修改。

例如:

public class AliasAttribute : System.Web.Mvc.CustomModelBinderAttribute 
{ 
    public AliasAttribute() 
    { 
    } 

    public AliasAttribute(string alias) 
    { 
     Alias = alias; 
    } 

    public string Alias { get; set; } 

    public override IModelBinder GetBinder() 
    { 
     var binder = new AliasModelBinder(); 

     if (!string.IsNullOrEmpty(Alias)) 
      binder.Alias = Alias; 

     return binder; 
    } 
} 

這然後允許這個用法:

public ActionResult Edit([Alias("somethingElse")] string email) 
{ 
    // ... 
}