MVC3 Remote Validation

2019-07-30 00:56发布

问题:

I am currently in the proccess of setting up remote validation using MVC3 so that a user is alerted if their chosen username already exists. Everything is set up and working correctly appart from the most important part, the error message not being displayed. If I submit the form the error message is displayed as the the page is refreshed with the relevant model state error added.

Is there anyway to refresh the model validation summary with a Json result?

回答1:

Sample code:

Web.config must contain this:

    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />

The view is like this:

@model Dommer.Domain.RegisterModel
@{
    ViewBag.Title = "Create";
}

<h2>Create New User</h2>

@using (Html.BeginForm())
{
    @Html.ValidationSummary(true, "Account creation was unsuccessful. Please correct the errors and try again.")
    <div>
        <fieldset>
            <legend>Account Information</legend>

            <div class="editor-label">
                @Html.LabelFor(m => m.UserName)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(m => m.UserName)
                @Html.ValidationMessageFor(m => m.UserName)
            </div>

            <div class="editor-label">
                @Html.LabelFor(m => m.Email)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(m => m.Email)
                @Html.ValidationMessageFor(m => m.Email)
            </div>

            <div class="editor-label">
                @Html.LabelFor(m => m.Password)
            </div>
            <div class="editor-field">
                @Html.PasswordFor(m => m.Password)
                @Html.ValidationMessageFor(m => m.Password)
            </div>

            <div class="editor-label">
                @Html.LabelFor(m => m.ConfirmPassword)
            </div>
            <div class="editor-field">
                @Html.PasswordFor(m => m.ConfirmPassword)
                @Html.ValidationMessageFor(m => m.ConfirmPassword)
            </div>
        </fieldset>
        <input type="submit" value="Create User" />
    </div>
}

This is the model being passed to the View:

public class RegisterModel
{
    [Required]
    [RegularExpression(@"(\S)+", ErrorMessage = "Username cannot contain spaces.")]
    [Remote("CheckUserName", HttpMethod="POST")]
    [Display(Name = "Username")]
    public string UserName { get; set; }

    [Required]
    [Remote("CheckEmailAddress", ErrorMessage="{0} already has an account, please enter a different email address.", HttpMethod="POST")]
    [DataAnnotationsExtensions.Email(ErrorMessage="{0} is not a valid email address.")]
    [Display(Name = "Email address")]
    public string Email { get; set; }

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

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}

This is in the controller

[HttpPost]
public JsonResult CheckUserName(string userName, Guid? userId = null)
{
    if (userName != null || userName.Length > 2)
    {
        var users = Membership.FindUsersByName(userName);
        if (users.Count == 0)
        {
                return Json(true);
        }
        else
        {
            if ((users[userName].ProviderUserKey as Guid?) == userId)
            {
                return Json(true);
            }
            else
            {
                string suggestedUID = String.Format(CultureInfo.InvariantCulture, "{0} is not available.", userName);
                for (int i = 1; i < 100; i++)
                {
                    string altCandidate = userName + i.ToString();
                    if (Membership.FindUsersByName(altCandidate).Count == 0)
                    {
                        suggestedUID = String.Format(CultureInfo.InvariantCulture, "{0} is not available. Try {1}.", userName, altCandidate);
                        break;
                    }
                }
                return Json(suggestedUID);
            }
        }
    }
    else
    {
        return Json(true);
    }
}

This will try appending numbers to the name until it finds an available username and will do something like this without doing a full postback: