2011-04-27 1 views
2

FluentValidation 프레임 워크를 사용하여 MVC 프로젝트의 모델에 유효성 검사 및 주석을 추가합니다.FluentValidation을 사용할 때 클래스에 DataAnnotation 추가

데이터 주석을 모델의 클래스 수준에 추가해야합니다. 즉, 모델에 DisplayColumn 특성이 추가되어야합니다. 그러나 FluentValidation을 사용하고 (응용 프로그램의 ModelMetadataProvider가 FluentValidation을 사용하도록 설정했기 때문에) 모델 클래스에 DisplayColumn 특성을 넣어도 사용되지 않습니다. 그러나 FluentValidation을 사용하여 해당 주석을 추가하는 방법을 찾을 수 없습니다.

아무도 내가 어떻게 작동하도록 할 수 있습니까?

감사

+0

1 년 후에도 규칙에 따라이 메타 데이터 공급자가 유용 할 수 있습니다. http://haacked.com/archive/2011/07/14/model-metadata-and-validation-localization-using-conventions.aspx – Luciano

답변

4

나는 실제로 FluentValidationModelMetadataProvider를 사용하는 것이 좋습니다 않을 것 - 이것은 단지 정말 지금까지 (아주 잘 다음 릴리스에서 제거 될 수 있습니다) 실험 또한이었으며, 클래스 중 하나를 지원하지 않습니다 (DisplayColumn과 같은) 수준의 DataAnnotations. 검증을 위해서만 FluentValidation을 사용하는 것이 좋지만 메타 데이터에 대한 속성을 고수하는 것이 좋습니다.

당신이 정말로이 다음 작업을 얻을하려는 경우 말했다되는, 당신은 사용자에게 메타 데이터만을 위해 사용되는 어떤 조합 검사기 사용하지으로 구현할 수 :

public static class MetadataExt { 
    public static IRuleBuilderOptions<T, TProperty> DisplayColumn<T, TProperty>(this IRuleBuilder<T, TProperty> rule) { 
     var ruleBuilder = (FluentValidation.Internal.RuleBuilder<T, TProperty>)rule; 
     ruleBuilder.Rule.AddValidator(new DisplayColumnWrapper(ruleBuilder.Rule.PropertyName)); 
     return ruleBuilder; 
    } 

    public class DisplayColumnWrapper : NoopPropertyValidator, IAttributeMetadataValidator { 
     private string name; 

     public DisplayColumnWrapper(string name) { 
      this.name = name; 
     } 

     public override IEnumerable<ValidationFailure> Validate(PropertyValidatorContext context) { 
      return Enumerable.Empty<ValidationFailure>(); 
     } 

     public Attribute ToAttribute() { 
      return new DisplayColumnAttribute(name); 
     } 
    } 
} 

... 당신은 다음처럼 사용할 수 이 :

public class ExtendedFVModelMetadataProvider : FluentValidationModelMetadataProvider { 
    IValidatorFactory _validatorFactory; 

    public ExtendedFVModelMetadataProvider(IValidatorFactory validatorFactory) 
     : base(validatorFactory) { 
     this._validatorFactory = validatorFactory; 
    } 

    public override ModelMetadata GetMetadataForType(Func<object> modelAccessor, Type modelType) { 
     var validator = _validatorFactory.GetValidator(modelType); 

     if (validator == null) { 
      return base.GetMetadataForType(modelAccessor, modelType); 
     } 

     // Only look for the DisplayColumnWrapper 
     // There is a mismatch as MVC expects this to be defined at class-level, but FV defines everything at the property level. 
     var displayColumns = from memberWithValidator in validator.CreateDescriptor().GetMembersWithValidators() 
          from propertyValidator in memberWithValidator 
          let wrapper = propertyValidator as MetadataExt.DisplayColumnWrapper 
          where wrapper != null 
          select wrapper.ToAttribute(); 

     var displayColumn = displayColumns.FirstOrDefault(); 

     // we found a displaycolumn, so pass it over to MVC to build the metadata. 
     if (displayColumn != null) { 
      return CreateMetadata(new[] { displayColumn }, null /* containerType */, modelAccessor, modelType, null /* propertyName */); 
     } 

     return base.GetMetadataForType(modelAccessor, modelType); 

    } 
} 
:

public class Validator : AbstractValidator<SomeModel> { 
    public Validator() { 
     RuleFor(x => x.DisplayColumnProperty) 
      .DisplayColumn(); 

    } 
} 

그런 다음이를 처리하는 방법을 알고있는 사용자 정의 ModelMetadataProvider를 만들 필요 했어

공급자는 GetMetadataForModel 메서드를 재정 의하여 DisplayColumn을 사용하는 모든 속성을 찾습니다. 다른 사용자 정의 메타 데이터 확장도 지원하려는 경우이 옵션을 확장 할 수 있습니다. 그런 다음 FluentValidation과 함께 제공되는 메타 데이터 공급자 대신이 공급자를 사용할 수 있습니다.

그러나이 방법은 권장하지 않습니다 ... 라이브러리는 UI 메타 데이터 생성을위한 것이 아니라 유효성 검사를 수행하도록 설계되었습니다.

+0

감사합니다. Jeremy. 나는 그것이 그것이 이런 것이 될 것이라고 생각했다. 엔티티 프레임 워크를 사용하기 때문에 FluentValidation에서이 기능을 사용했습니다. 속성에서 단순한 것으로 버디 클래스 "오염"을 정말 좋아하지 않습니다. 밸리데이션을 위해서만 FluentValidation을 사용할 수있는 또 다른 방법이 있는지 알고 있습니까? –

+0

친구 클래스 방식은 실제로 매우 끔찍합니다. 내가 아는 다른 메타 데이터 공급자는 http://weblogs.asp.net/rashid/archive/2009/12/24/introducing-fluent-metadataprovider-for-asp-net-mvc에 언급 된 'Fluent MetadataProvider'뿐입니다. .aspx하지만 불행히도 코드는 더 이상 사용할 수없는 것 같습니다. FluentValidation의 차후 버전에서 더 나은 메타 데이터 공급자를 구현하는 방법을 살펴볼 수도 있습니다. 그러나 현재는 사물의 유효성 검사 측면에만 초점을 맞추고 있습니다. –