2013-08-16 71 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) 
{ 
    // ... 
}