3

カスタム検証コードから次の情報を返す方法を探しています。

public enum ValidationErrorTypeFlags
{
    Error_Input = 1 << 0,               // a "field specific" error which is checked both clientside and serverside 
    Error_Input_ServerSide = 1 << 1,    // a "field specific" error which can only be checked serverside
    Error_General = 1 << 2              // serverside general error
}

検証コード (IValidatableObject または ValidationAttribute のいずれか) 内で、エラーを検出したときに、上記のエラーの種類のいずれかを ValidationResult に関連付けられるようにしたいと考えています。

次に、コントローラーまたはビューのいずれかで検証エラーを反復処理し、これらのエラーの種類を区別できるようにしたいと考えています。

私は現在 MVC 3 を使用しています (4 にアップグレードできてうれしいです)。

注意:

  • ModelState は ValidationResults AFAIK を保持しません - ViewData.ModelState.Values.Items[x].Errors のエラーにのみアクセスできます - これらは System.Web.Mvc.ModelError に変換されています
  • MVC 検証では、検証が完了した後にのみ [key, 'error message'] タイプの検証結果にアクセスできるようです。

私が現在使用しているハックは、カスタム検証コード内のエラー メッセージを装飾することです。

var field = new[] { validationContext.DisplayName };
return new ValidationResult("+Invalid format - use yyyy-mm-dd", field);

次に、コントローラで +、-、* で始まるエラー メッセージを探します。

4

1 に答える 1

3

カスタム検証コード (組み込みのものから達成する方法がわからない)ValidationResultから、ベースから継承してカスタム検証属性から返すことでカスタム クラスを作成することでそれを行うことができます。

public class CustomValidationResult: ValidationResult
{
   // additional properties
}

次に、コントローラーからキャストして、検証結果がカスタムタイプであるかどうかを確認し、それに応じて動作させることができます。

アップデート:

ValidationResultクラスが DataAnnotations アセンブリにあり、それらが変換されModelValidationResult、MVC でアクセスできるのはそれだけであるため、上記のアイデアは機能しません。

データ注釈の検証から MVC に追加情報を渡すのは簡単ではないようです。

ソースコードを調べていたところ、ValidatableObjectAdapterを に変換するのは であることがわかりIEnumerable<ValidationResult>ましたIEnumerable<ModelValidationResult>。このクラスを拡張するメリットはあまりないと思いますが、 をValidatableObjectAdapter実装してコードModelValidatorを複製することでカスタムを簡単に作成できます。Validate

ModelValidationResultカスタムとカスタムを作成する必要があり (検証から返されるのValidationResultはこのカスタムです) 、追加情報を処理する変換コードをメソッドに入れることができます。ValidationResultConvertResults

public class CustomValidatableObjectAdapter : ModelValidator
{
    public CustomValidatableObjectAdapter(ModelMetadata metadata, ControllerContext context)
      : base(metadata, context)
    {
    }

    public override IEnumerable<ModelValidationResult> Validate(object container)
    {
      object model = Metadata.Model;
      if (model == null)
      {
        return Enumerable.Empty<ModelValidationResult>();
      }

      IValidatableObject validatable = model as IValidatableObject;
      if (validatable == null)
      {
        throw new Exception("model is of not type validatable");
      }

      ValidationContext validationContext = new ValidationContext(validatable, null, null);

      return ConvertResults(validatable.Validate(validationContext));
    }

    private IEnumerable<ModelValidationResult> ConvertResults(IEnumerable<ValidationResult> results)
    {
      foreach (ValidationResult result in results)
      {
        // iterate the ValidationResult enumeration and cast each into CustomValidationResult
        // and conver them into enumeration of CustomModelValidationResult.
      }
    }
}

最後に、Global.asax.csの場合にDataAnnotationsModelValidatorProviderこれを使用するように指示する必要があります。CustomValidatableObjectAdapterApplication_Start

DataAnnotationsModelValidatorProvider.RegisterDefaultValidatableObjectAdapterFactory((metadata, context) => new CustomValidatableObjectAdapter(metadata, context));

したがって、 custom ValidationResult、 custom ModelValidationResult、およびcustom を作成する必要がありますValidatableObjectAdapter

私はこれをテストしていませんが、うまくいくことを願っています。これよりも優れた簡単な解決策を提案するかもしれません。

于 2012-06-16T04:21:46.773 に答える