web-dev-qa-db-ja.com

流暢な検証カスタム検証ルール

私はモデルを持っています:

_[Validator(typeof(RegisterValidator))]
public class RegisterModel
{
    public string Name { get; set; }

    public string Email { get; set; }

    public string Password { get; set; }

    public string ListOfCategoriess { get; set; }
}
_

そしてモデルのバリデーター:

_public class RegisterValidator:AbstractValidator<RegisterModel>
{
    public RegisterValidator(IUserService userService)
    {
        RuleFor(x => x.Name).NotEmpty().WithMessage("User name is required.");
        RuleFor(x => x.Email).NotEmpty().WithMessage("Email is required.");
        RuleFor(x => x.Email).EmailAddress().WithMessage("Invalid email format.");
        RuleFor(x => x.Password).NotEmpty().WithMessage("Password is required.");
        RuleFor(x => x.ConfirmPassword).NotEmpty().WithMessage("Please confirm your password.");
    }
}
_

依存関係を解決するバリデータファクトリがあります。

_public class WindsorValidatorFactory : ValidatorFactoryBase 
{
    private readonly IKernel kernel;

    public WindsorValidatorFactory(IKernel kernel)
    {
        this.kernel = kernel;
    }

    public override IValidator CreateInstance(Type validatorType)
    {
        if (validatorType == null)
            throw new Exception("Validator type not found.");
        return (IValidator) kernel.Resolve(validatorType);
    }
}
_

メソッドIsUsernameUnique(string name)とIsEmailUnique(string email) `を持つIUserServiceがあり、それをバリデータークラスで使用したいと考えています(モデルは一意のユーザー名と電子メールがある場合にのみ有効である必要があります)。

  1. 検証のために私のサービスを使用する方法は?
  2. 異なるエラーメッセージで複数の正規表現ルールを登録することは可能ですか?クライアント側で動作しますか? (いいえの場合、カスタム検証ロジックを作成する方法は?)
  3. サーバー側の検証は、モデルがアクションメソッドに渡される前に自動的に機能し、ModelState.IsValidプロパティを呼び出すだけで十分ですか、それとももっと何かをする必要がありますか? [〜#〜]更新[〜#〜]
  4. 一部のプロパティを検証するときに、モデルのすべてのプロパティにアクセスすることは可能ですか? (たとえば、登録時にパスワードとConfirmPasswordを比較したい)
12
Evgeny Levin

1)検証のために私のサービスを使用する方法は?

Mustルールを使用できます。

RuleFor(x => x.Email)
    .NotEmpty()
    .WithMessage("Email is required.")
    .EmailAddress()
    .WithMessage("Invalid email format.")
    .Must(userService.IsEmailUnique)
    .WithMessage("Email already taken");

2)異なるエラーメッセージで複数の正規表現ルールを登録することは可能ですか?クライアント側で動作しますか? (いいえの場合、カスタム検証ロジックを作成する方法は?)

いいえ、プロパティごとに1つの検証タイプしか持てません

いいえの場合、カスタム検証ロジックを作成する方法は?

Mustルールを使用できます。

RuleFor(x => x.Password)
    .Must(password => SomeMethodContainingCustomLogicThatMustReturnBoolean(password))
    .WithMessage("Sorry password didn't satisfy the custom logic");

3)サーバー側の検証は、モデルがアクションメソッドに渡される前に自動的に機能し、ModelState.IsValidプロパティを呼び出すだけで十分ですか、それとももっと何かをする必要がありますか?

そのとおり。コントローラのアクションは次のようになります。

[HttpPost]
public ActionResult Register(RegisterModel model)
{
    if (!ModelState.IsValid)
    {
        // validation failed => redisplay the view so that the user
        // can fix his errors
        return View(model);
    }

    // at this stage the model is valid => process it
    ...
    return RedirectToAction("Success");
}

更新:

4)一部のプロパティを検証するときに、モデルのすべてのプロパティにアクセスすることは可能ですか? (たとえば、登録時にパスワードとConfirmPasswordを比較したい)

はい、もちろん:

RuleFor(x => x.ConfirmPassword)
    .Equal(x => x.Password)
    .WithMessage("Passwords do not match");
21
Darin Dimitrov

より良い変形は、RuleBuilderExtensionを使用することです。

public static class RuleBuilderExtensions
{
    public static IRuleBuilder<T, string> Password<T>(this IRuleBuilder<T, string> ruleBuilder, int minimumLength = 14)
    {
        var options = ruleBuilder
            .NotEmpty().WithMessage(ErrorMessages.PasswordEmpty)
            .MinimumLength(minimumLength).WithMessage(ErrorMessages.PasswordLength)
            .Matches("[A-Z]").WithMessage(ErrorMessages.PasswordUppercaseLetter)
            .Matches("[a-z]").WithMessage(ErrorMessages.PasswordLowercaseLetter)
            .Matches("[0-9]").WithMessage(ErrorMessages.PasswordDigit)
            .Matches("[^a-zA-Z0-9]").WithMessage(ErrorMessages.PasswordSpecialCharacter);
        return options;
    }

このようにして、使用するのは簡単になります。

RuleFor(x => x.Password).Password();
11
MovGP0