1

I'm currently working on a registration page where the users enter their email address. I want every email to be unique.

This is a part of my RegisterModel:

    [Required()]
    [System.Web.Mvc.Remote("IsUserEmailAvailable", "Account")]
    [EmailAddress()]
    [DataType(DataType.EmailAddress)]
    [Display(Name = "Email")]
    public string Email { get; set; }

..

This is a part of my accountcontroller:

    public JsonResult IsUserEmailAvailable(string UserEmail)
    {
        return Json(!db.UserProfiles.Any(User => User.UserName == UserEmail),       JsonRequestBehavior.AllowGet);
    }

This my my view:

<script src="~/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="~/Scripts/jquery.validate.min.js" type="text/javascript"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>


<hgroup class="title">
    <h1>Create Account</h1>
</hgroup>

@using (Html.BeginForm()) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()

    <fieldset>
        <legend>Registration Form</legend>
        <ol>
            <li>
                @Html.LabelFor(m => m.UserName)
                @Html.TextBoxFor(m => m.UserName)
            </li>
            <li>
                @Html.LabelFor(m => m.Password)
                @Html.PasswordFor(m => m.Password)
            </li>
            <li>
                @Html.LabelFor(m => m.ConfirmPassword)
                @Html.PasswordFor(m => m.ConfirmPassword)
            </li>
            <li>
                @Html.LabelFor(m => m.Email)
                @Html.TextBoxFor(m => m.Email)
            </li>
            <li>
                @Html.LabelFor(m => m.ConfirmEmail)
                @Html.TextBoxFor(m => m.ConfirmEmail)
            </li>
        </ol>
        <input type="submit" value="Registrera" />
    </fieldset>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

If I remove the [System.Web.Mvc.Remote("IsUserEmailAvailable", "Account")] everything is fine except the emailaddress wont be unique. With it, when I press the Submit, nothing happens.

Have I missed anything?

Reft
  • 2,333
  • 5
  • 36
  • 64

3 Answers3

0

The [Remote] attribute is quite limited and requires the name of the property to be the same as the name of the parameter in the controller action.

  • Your property is named Email as in public string Email { get; set; }

  • Your action has a parameter named UserEmail as in IsUserEmailAvailable(string UserEmail)

This won't work, because the remote validation will end up sending a request to validate the field like:

Account/IsUserEmailAvailable?Email=foo

Where Email is the name of the property. Actually, it is the name attribute of the rendered html input field. This might be a problem with nested models, where the name will be something like NestedModel.Email, but luckily it is not your case. (See for example this question)

So your validation method is receiving UserEmail as null (because the request contains a single parameter named Email), which might be causing the request to fail. (Have you checked the console in your browser to see if the ajax request failed?)

As both names should match, you could update your controller action so the parameter is named Email:

public JsonResult IsUserEmailAvailable(string Email)
{
    ...
}

Hope it helps!

Community
  • 1
  • 1
Daniel J.G.
  • 34,266
  • 9
  • 112
  • 112
  • I have edited my action: public JsonResult IsUserEmailAvailable(string Email) { return Json(!db.UserProfiles.Any(User => User.Email == Email), JsonRequestBehavior.AllowGet); } Same here, nothing happens. Also it doesn't say anything about the ajax request, everything is blank. – Reft Feb 05 '14 at 17:46
  • This is from the network tab in chrome: Location: /Account/Login?ReturnUrl=%2fAccount%2fIsEmailAvailable%3fEmail%3dmyslex%2540gmail.com&Email=myslex%40gmail.com [18:36:12] Request URL:http://localhost:60576/Account/IsEmailAvailable?Email=myslex%40gmail.com Request Method:GET Status Code:302 Found – Reft Feb 05 '14 at 17:47
  • Also, in my AccountModel i couldnt include the namespace using System.Web.Mvc; My [Compare] attributes on my other lines went red and it said "namespace couldnt be found blablabla" so i included it as you see it now, on a single line before remote attribute. Thanks for all your help – Reft Feb 05 '14 at 17:49
  • 1
    Looking at the url `/Account/Login?ReturnUrl=%2fAccount%2fIsEmailAvailable%3fEmail%3dmyslex%2540gmai‌​l.com&Email=myslex%40gmail.com` could it be that your validation method is in a controller that requires users to be authenticated? Because the response is redirecting users to the login page... – Daniel J.G. Feb 05 '14 at 17:51
  • When i try to register a new user and tab from the email textbox it never reaches the action method in the debugger – Reft Feb 05 '14 at 17:55
  • That's what I mean, if that validation method is in a controller with the [Authorize] attribute (or if the filter has been globally registered...) it will never reach that method unless the user was authenticated first – Daniel J.G. Feb 05 '14 at 18:03
0

You could setup a MVC controller action and use jquery to query it on-the-fly. Here is an article that explains ways to do it (Be advised it is for an auto-complete textbox but the theory is the same): How Do I Create an Auto-Complete TextBox?

I would be very interested in seeing the solution you come up with to accomplish this task.

FrankO
  • 2,522
  • 6
  • 24
  • 34
0

@Daniel J.G. is correct. Adding [AllowAnonymous] to the function makes it accessible.

myslex
  • 184
  • 1
  • 2
  • 9
  • Yes thank you mister, it works now. stupid me. I had a global filter, filters.Add(new System.Web.Mvc.AuthorizeAttribute()); – Reft Feb 05 '14 at 18:03