0

ASP.NETMVC1.0からASP.NETMVC2 Betaに切り替えた後、いくつかの異なる動作が発生しています。重大な変更を確認しましたが、問題がどこにあるのか明確ではありません。

問題は、デフォルトのモデルバインダーとIDataErrorInfoを実装するモデルに関係しています。

プロパティ(IDataErrorInfo.Item):

public string this[string columnName]

プロパティごとに呼び出されることはなくなりました。私は何が欠けていますか?

4

2 に答える 2

1

MVC 1.0のDefaultModelBinder:

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);
        }
    }
}

MVC 2.0ベータ版の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 this [string 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());

そしてそれは機能します:)これは単なる一時的な解決策です。最終的なMVC2で修正する必要があります。

編集

また、。のメソッドでif (base.Metadata.Model != null)if(container!= null)に変更しました。Validate()DataErrorInfoPropertyModelValidator

于 2009-11-19T20:42:47.127 に答える
1

さらにデバッグ作業を行った後、特定のケースでIDataErrorInfo.Itemが呼び出されない理由を理解できたと思います。次のコードは、ASP.NETMVC2ベータ版でIDataErrorInfoプロパティを検証するために使用されます。

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>();
    }
}

私のモデルには次のプロパティが含まれておりSystem.Nullable<int>、モデルバインダーがHTML投稿からの空の文字列をバインドすると、Metadata.Modelはnullに等しいため、検証は実行されません。

これは、ASP.NET MVC 1.0とは根本的に異なります。ASP.NETMVC1.0では、このシナリオでは、への呼び出しまでバリデーターが起動されIDataErrorInfo.Itemます。

意図したとおりに使用していないだけですか?

于 2009-11-20T05:15:10.337 に答える