2013-08-16 2 views
2

비슷한 게시물이 많이 있지만 컨트롤러 parameters에 대한 답변을 찾지 못했습니다.모델 바인딩시 매개 변수에 대한 사용자 지정 속성 가져 오기

모델 바인딩 중에 매개 변수의 별칭을 정의 할 수있는 AliasAttribute이라는 사용자 지정 특성을 작성했습니다. 그래서 예를 들어 내가있는 경우 : 서버에 public JsonResult EmailCheck(string email)와 나는 email 매개 변수 내가 "지도"를 할 수 SomeCrazyEmailPrimaryEmail 또는 라는 이름의 필드에 바인딩 할이이 같은 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) 
{ 
    // ... 
}