0

私はモジュールレベルのバリデーターを使用しています:ビューモデルで「PropertiesMustMatch」のように:

[PropertiesMustMatch("Password", "PasswordConfirm")]
public class HomeIndex
{
    [Required]
    public string Name { get; set; }

    public string Password { get; set; }

    public string PasswordConfirm { get; set; }
}

名前を入力せずにフォームを送信すると、ValidationSummary()ヘルパーが次のエラーのみを返すことに気づきました。

  • [名前]フィールドは必須です。

ただし、Nameを入力すると ValidationSummary()はPropertiesMustMatchエラーを返します。

  • 「Password」と「PasswordConfirm」が一致しません。

したがって、プロパティレベルのバリデーターが最初に評価され、次にモデルレベルのバリデーターが評価されているように見えます。

それらがすべて一度に検証され、ValidationSummaryが次のように返される場合は非常に望ましいです。

  • [名前]フィールドは必須です。
  • 「Password」と「PasswordConfirm」が一致しません。

これを修正するために私ができることはありますか?

私はMVC2のソースコードを調べて、これが発生する理由を特定しようとしています。

4

1 に答える 1

0

私はこれを引き起こしているものを見つけましたが、私の「解決策」はおそらくバリデーターの通常の処理を壊すでしょう。注意して使用してください。

DefaultModelBinderのOnModelUpdated関数に条件付きのreturnステートメントが見つかりました。

protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
    IDataErrorInfo errorProvider = bindingContext.Model as IDataErrorInfo;
    if (errorProvider != null)
    {
        string errorText = errorProvider.Error;
        if (!String.IsNullOrEmpty(errorText))
        {
            bindingContext.ModelState.AddModelError(bindingContext.ModelName, errorText);
        }
    }

    // BEGIN CONDITION
    if (!IsModelValid(bindingContext))
    {
        return;
    }
    // END CONDITION

    foreach (ModelValidator validator in bindingContext.ModelMetadata.GetValidators(controllerContext))
    {
        foreach (ModelValidationResult validationResult in validator.Validate(null))
        {
            bindingContext.ModelState.AddModelError(CreateSubPropertyName(bindingContext.ModelName, validationResult.MemberName), validationResult.Message);
        }
    }
}

私がこのコードを理解している場合(私は理解していないかもしれませんが)、MVCチームはこの時点でモデルバリデーターをスキップすることを意図していたようです。

条件によって回避されたはずのコードを再実行する独自のカスタムModelBinderを作成しました。

public class CustomModelBinder : DefaultModelBinder
{
    protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        base.OnModelUpdated(controllerContext, bindingContext);

        foreach (ModelValidator validator in bindingContext.ModelMetadata.GetValidators(controllerContext))
        {
            foreach (ModelValidationResult validationResult in validator.Validate(null))
            {
                bindingContext.ModelState.AddModelError(CreateSubPropertyName(bindingContext.ModelName, validationResult.MemberName), validationResult.Message);
            }
        }
    }
}

これで問題が解決したようです。

于 2010-05-30T05:11:03.973 に答える