简体   繁体   中英

Fluent Validation with MVC5

I am admittedly still very green in the realm of C# and MVC5, but learning more everyday, so your patience with my lack of knowledge is greatly appreciated.

I have read everything I could find and can still not get the following to work. Truthfully I tried to get the cleaner .Trial(password) to work, but realized that was probably over my head. That would be preferred, but at least getting this ugly version to work would be fantastic. The "trial" method does not get called from what I can tell, but can not check as I get an error when I try to debug it with a breakpoint.

.

I have the following in my AccountViewModels.cs

[Validator(typeof(RegisterViewModelValidator))]
public class RegisterViewModel {
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Display(Name = "Email")]
    public string Email { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    public string ConfirmPassword { get; set; }


}




public class RegisterViewModelValidator : AbstractValidator<RegisterViewModel> {
    public RegisterViewModelValidator() {

        RuleFor(x => x.UserName)
            .NotEmpty()
                .WithMessage("Username is required");

        RuleFor(x => x.Email)
            .NotNull()
                .WithMessage("E-mail is required")
            .EmailAddress()
                .WithMessage("E-mail is invalid");

        RuleFor(x => x.Password)
           .Must(password => Trial(password))
                .WithMessage("Password must triggered");

        RuleFor(x => x.ConfirmPassword)
            .Equal(x => x.Password)
                .WithMessage("Confimation odes not match");

    }

    private bool Trial(string value) {
        if (string.IsNullOrEmpty(value)) {
            return false;
        } else {
            return true;
        }
    }
}

and the following in my Global.asax

 FluentValidation.Mvc.FluentValidationModelValidatorProvider.Configure();

and this is in my view

<div id="regesterFormContainer" class="col-md-4">


            @using (Html.BeginForm("Register", "Account", FormMethod.Post, new { id = "regesterForm", autocomplete = "off" })) {

                @Html.AntiForgeryToken()


                @Html.ValidationMessageFor(m => m.UserName, string.Empty, new { @class = "error-class" })
                @Html.TextBoxFor(m => m.UserName, new { id = "regesterUserNam", placeholder = "Username", @class = "registerFormInputs", title = "4-20 characters with letters, numbers, - and _" })


                @Html.ValidationMessageFor(m => m.Email, string.Empty, new { @class = "error-class" })
                @Html.TextBoxFor(m => m.Email, new { id = "regesterEhMell", placeholder = "E-Mail Address", @class = "registerFormInputs", title = "Must be a valid e-mail address." })


                @Html.ValidationMessageFor(m => m.Password, string.Empty, new { @class = "error-class" })
                @Html.PasswordFor(m => m.Password, new { id = "regesterPess", placeholder = "Password", @class = "registerFormInputs", title = "5-20 characters. An Uppercase letter, lowercase letter and a number are required." })

                @Html.ValidationMessageFor(m => m.ConfirmPassword, string.Empty, new { @class = "error-class" })
                @Html.PasswordFor(m => m.ConfirmPassword, new { id = "regesterConPess", placeholder = "Confirm Password", @class = "registerFormInputs", title = "Must match password above." })


                <div class="registerSubmitFrame">
                    <input type="submit" class="registerSubmit" value="Register">
                </div>
                <p><a id="showExtReg">Show external registration options</a></p>


            }



        </div>

The applicable controller chunk

 [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Register(RegisterViewModel model) {
            if (ModelState.IsValid) {
                var user = new ApplicationUser { UserName = model.UserName, Email = model.Email };
                var result = await UserManager.CreateAsync(user, model.Password);


                var validator = new RegisterViewModelValidator();
                validator.Validate(model);  // viewmodel should be passed into the controller method on POST via model binding.



                if (result.Succeeded) {
                    await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);

                    // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
                    // Send an email with this link
                    // string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
                    // var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
                    // await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>");

                    return RedirectToAction("Index", "Home");
                }
                AddErrors(result);
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

I appreciate your time and patience

Try:

RuleFor(x => x.Password)
    .NotEmpty()
         .WithMessage("Password in required")
    .Length(6, 100)
        .WithMessage("Password not long enough")
    .Must(Trial)
        .WithMessage("Password must triggered");

private bool Trial(RegisterViewModel viewModel, string value) {
    if (string.IsNullOrEmpty(value)) {
        return false;
    } else {
        return true;
    }
}

You may have an issue binding your view model in the controller handling the POST. Show us your controller code.

You can put this in your controller to verify this:

var validator = new RegisterViewModelValidator();
validator.Validate(viewModel);  // viewmodel should be passed into the controller method on POST via model binding.

EDIT: To Clarify,

The following validators are supported on the client:

NotNull/NotEmpty
Matches (regex)
InclusiveBetween (range)
CreditCard
Email
EqualTo (cross-property equality comparison)
Length

In OP's case he should be using "NotEmpty" which would take the place of this "Must" logic:

   private bool Trial(string value) {
        if (string.IsNullOrEmpty(value)) {
            return false;
        } else {
            return true;
        }
    }

AND it would run both on the jquery unobtrusive Client and Server MVC model validations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM