1

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?

Ryan Smith
  • 475
  • 1
  • 8
  • 19
  • 1
    This should work. Do you definitely have unobtrusive validation working? Does your controller action get hit and is it returning a Json result? – Tom Chantler Jan 20 '12 at 17:03

1 Answers1

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:

enter image description here

Tom Chantler
  • 14,753
  • 4
  • 48
  • 53
  • Nice Solution, still doesn't work for me though. The request is being proccessed and passed back, the box is even being styled in the chosen manner. The only problem is with no text being displayed. Should the validation summary be 'refreshed' on the result of a false Json request? I'm really confused by this, I've been at it for ages. – Ryan Smith Jan 20 '12 at 17:16
  • 1
    I have this code working (I even just tried it now this minute), so there must be something different going on... – Tom Chantler Jan 20 '12 at 17:18
  • Maybe a daft question, but are you actually displaying the validation message? See the update to my answer (the view code snippet)... – Tom Chantler Jan 20 '12 at 17:20
  • Yeah, this is maddness... I don't have a clue why there are no messages being displayed. – Ryan Smith Jan 20 '12 at 17:25
  • Are you saying that the text box is being coloured correctly (e.g. going red/pink if using default css)? If so then it must be something about the layout that's not working. – Tom Chantler Jan 20 '12 at 17:50
  • Yes, everything is working as expected except from the actual error message – Ryan Smith Jan 20 '12 at 17:52
  • Could you show me what your view looks like Dommer? It is clearly a view issue. – Ryan Smith Jan 20 '12 at 17:57
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/6902/discussion-between-dommer-and-user1084453) – Tom Chantler Jan 20 '12 at 18:03