2009-11-19 2 views
0

ASP.NET MVC 1.0에서 ASP.NET MVC 2 베타로 전환 한 후 다른 동작이 발생합니다. 나는 깨진 변화를 확인했지만 문제가 어디에 있는지 분명하지 않다.ASP.NET MVC 2 베타 - 기본 모델 바인더

문제는 기본 모델 바인더와 IDataErrorInfo를 구현하는 모델과 관련이 있습니다.

속성 (IDataErrorInfo.Item는) :

public string this[string columnName] 

는 더 이상 각각의 속성에 대해 호출되지되고있다. 내가 뭘 놓치고 있니? MVC 1.0

+0

광산과 중복되는 경우 : http://stackoverflow.com/questions/1760039/is-idataerrorinfo-ignored-during-model-validation-in-mvc-2 – LukLed

+0

답변이없는 것 같습니다. 유효성 검사는 작동하지만 다르게 동작합니다. 필자의 경우 System.Nullable 과 같은 간단한 유형의 경우. – Rudy

답변

1

일부 디버깅 작업을 마친 후 나는 왜 내 특별한 경우에 IDataErrorInfo.Item이 호출되지 않는지 이해한다고 생각합니다. 다음 코드는 IDataErrorInfo 특성의 유효성을 검사하기 위해 ASP.NET MVC 2 베타에서 사용되는 : 내 모델이 System.Nullable<int>을하고 속성을 포함

internal sealed class DataErrorInfoPropertyModelValidator : ModelValidator 
{ 
    public DataErrorInfoPropertyModelValidator(ModelMetadata metadata, ControllerContext controllerContext) 
     : base(metadata, controllerContext) 
    { 
    } 

    public override IEnumerable<ModelValidationResult> Validate(object container) 
    { 
     if (Metadata.Model != null) 
     { 
      var castContainer = container as IDataErrorInfo; 
      if (castContainer != null) 
      { 
       string errorMessage = castContainer[Metadata.PropertyName]; 
       if (!String.IsNullOrEmpty(errorMessage)) 
       { 
        return new[] { new ModelValidationResult { Message = errorMessage } }; 
       } 
      } 
     } 
     return Enumerable.Empty<ModelValidationResult>(); 
    } 
} 

을 모델 바인더는 HTML의 게시물에서 빈 문자열을 결합하면, Metadata.Model 따라서 null은 유효하지 않으므로 유효성 검사가 실행되지 않습니다.

이것은 ASP.NET MVC 1.0과 근본적으로 다른데,이 시나리오에서는 유효성 검사기가 완료되어 IDataErrorInfo.Item으로 호출됩니다.

의도 한대로 사용하지 않고 있습니까?

+0

신고 해 주셔서 감사합니다. 나는 다른 MVC 개발자들과 이야기를 나누었고, null 체크는 Preview 2와 Beta 사이의 어떤 시점에서 목적을 달성했다고 의심해 왔지만 이후에는 불필요하게 렌더링되었다. 나는 수표를 제거하기 위해 버그를 신청했다. – Levi

+0

감사합니다. – Rudy

1

DefaultModelBinder : MVC 2.0 베타

protected virtual void OnPropertyValidated(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value) 
{ 
    IDataErrorInfo model = bindingContext.Model as IDataErrorInfo; 
    if (model != null) 
    { 
     string str = model[propertyDescriptor.Name]; 
     if (!string.IsNullOrEmpty(str)) 
     { 
      string key = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name); 
      bindingContext.ModelState.AddModelError(key, str); 
     } 
    } 
} 

DefaultModelBinder :

protected virtual void OnPropertyValidated(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value) 
{ 
    ModelMetadata metadata = bindingContext.PropertyMetadata[propertyDescriptor.Name]; 
    metadata.Model = value; 
    string prefix = CreateSubPropertyName(bindingContext.ModelName, metadata.PropertyName); 
    foreach (ModelValidator validator in metadata.GetValidators(controllerContext)) 
    { 
     foreach (ModelValidationResult result in validator.Validate(bindingContext.Model)) 
     { 
      bindingContext.ModelState.AddModelError(CreateSubPropertyName(prefix, result.MemberName), result.Message); 
     } 
    } 
    if ((bindingContext.ModelState.IsValidField(prefix) && (value == null)) && !TypeHelpers.TypeAllowsNullValue(propertyDescriptor.PropertyType)) 
    { 
     bindingContext.ModelState.AddModelError(prefix, GetValueRequiredResource(controllerContext)); 
    } 
} 

그것은 IDataErrorInfo이 [문자열 COLUMNNAME] 속성을 사용하지 않습니다는 ... 때문에, 벌레처럼 보인다 DefaultModelBinder는 여전히 Error 속성을 사용합니다. 그것은 적어도 모순입니다.

편집

내가 반사경을 사용 DataErrorInfoPropertyModelValidator 사용하지 않는 것 것으로 나타났습니다, 그래서 난 내 자신의 클래스 생성 :

public class DataErrorInfoModelPropertyValidatorProvider : ModelValidatorProvider 
{ 
    // Methods 
    public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context) 
    { 
     if (metadata == null) 
     { 
      throw new ArgumentNullException("metadata"); 
     } 
     if (context == null) 
     { 
      throw new ArgumentNullException("context"); 
     } 

     var validators = new List<ModelValidator>(); 
     validators.Add(new DataErrorInfoPropertyModelValidator(metadata, context)); 
     return validators; 
    } 

    internal sealed class DataErrorInfoPropertyModelValidator : ModelValidator 
    { 
     // Methods 
     public DataErrorInfoPropertyModelValidator(ModelMetadata metadata, ControllerContext controllerContext) 
      : base(metadata, controllerContext) 
     { 
     } 

     public override IEnumerable<ModelValidationResult> Validate(object container) 
     { 
      if (container != null) 
      { 
       IDataErrorInfo info = container as IDataErrorInfo; 
       if (info != null) 
       { 
        string str = info[Metadata.PropertyName]; 
        if (!string.IsNullOrEmpty(str)) 
        { 
         ModelValidationResult[] resultArray = new ModelValidationResult[1]; 
         ModelValidationResult result = new ModelValidationResult(); 
         result.Message = str; 
         resultArray[0] = result; 
         return resultArray; 
        } 
       } 
      } 
      return Enumerable.Empty<ModelValidationResult>(); 
     } 
    } 
} 

그럼 내가 사용 :

ModelValidatorProviders.Providers.Add(new DataErrorInfoModelPropertyValidatorProvider()); 

그리고 그것은 작동합니다 :) 이것은 단지 일시적인 해결책입니다. DataErrorInfoPropertyModelValidatorValidate() 방법에 최종 MVC 2

나는 또한 경우에 if (base.Metadata.Model != null)을 변경

EDIT (용기! = null이) 수정해야합니다.

+0

metaData.GetValidators를 호출하면 DataErrorInfoPropertyModelValidator가 생성됩니다.Validate를 호출하면 IDataErrorInfo 인터페이스를 직접 호출해야합니다. 그것은 단지 그렇게까지 그렇게 보이지 않는 것 같습니다. – Rudy

관련 문제