Удаленная проверка MVC (уникальный адрес электронной почты)

В настоящее время я работаю над страницей регистрации, где пользователи вводят свой адрес электронной почты. Я хочу, чтобы каждое письмо было уникальным.

Это часть моей модели RegisterModel:

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

..

Это часть моего аккаунт-контроллера:

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

Это мой взгляд:

<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")
}

Если я удалю [System.Web.Mvc.Remote("IsUserEmailAvailable", "Account")] все будет в порядке, за исключением того, что адрес электронной почты не будет уникальным. С ним, когда я нажимаю Submit, ничего не происходит.

Я ничего не пропустил?


person Reft    schedule 05.02.2014    source источник
comment
Можешь показать свою точку зрения? возможно, вы пропустили отображение ошибки проверки Html.ValidationMessageFor   -  person Alexandr Mihalciuc    schedule 05.02.2014
comment
Попробуйте добавить html.ValidationMesageДля вашей электронной почты   -  person Alexandr Mihalciuc    schedule 05.02.2014


Ответы (3)


@ Дэниел Дж. Г. верно. Добавление [AllowAnonymous] к функции делает ее доступной.

person myslex    schedule 05.02.2014
comment
Да, спасибо, мистер, теперь работает. глупый я. У меня был глобальный фильтр filter.Add(new System.Web.Mvc.AuthorizeAttribute()); - person Reft; 05.02.2014

Атрибут [Remote] весьма ограничен и требует, чтобы имя свойства совпадало с именем параметра в действии контроллера.

  • Ваша собственность называется Email как в public string Email { get; set; }

  • У вашего действия есть параметр с именем UserEmail, например IsUserEmailAvailable(string UserEmail).

Это не сработает, потому что удаленная проверка в конечном итоге отправит запрос на проверку поля, например:

Account/IsUserEmailAvailable?Email=foo

Где Email — имя свойства. На самом деле, это атрибут имени отображаемого поля ввода html. Это может быть проблемой для вложенных моделей, где имя будет примерно таким, как NestedModel.Email, но, к счастью, это не ваш случай. (см., например, этот вопрос)

Таким образом, ваш метод проверки получает UserEmail как null (поскольку запрос содержит единственный параметр с именем Email), что может привести к сбою запроса. (Вы проверили консоль в своем браузере, чтобы убедиться, что запрос ajax не удался?)

Поскольку оба имени должны совпадать, вы можете обновить действие контроллера, чтобы параметр назывался Email:

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

Надеюсь, поможет!

person Daniel J.G.    schedule 05.02.2014
comment
Я отредактировал свое действие: public JsonResult IsUserEmailAvailable(string Email) { return Json(!db.UserProfiles.Any(User => User.Email == Email), JsonRequestBehavior.AllowGet); } Здесь тоже ничего не происходит. Также ничего не говорится о запросе ajax, все пусто. - person Reft; 05.02.2014
comment
Это на вкладке сети в Chrome: Location: /Account/Login?ReturnUrl=%2fAccount%2fIsEmailAvailable%3fEmail%3dmyslex%2540gmail.com&Email=myslex%40gmail.com [18:36:12] URL-адрес запроса: localhost:60576/Account/ Метод запроса: GET Код состояния: 302 Found - person Reft; 05.02.2014
comment
Кроме того, в моей AccountModel я не мог включить пространство имен, используя System.Web.Mvc; Мои атрибуты [Compare] в других моих строках стали красными, и в нем говорилось, что пространство имен не может быть найдено blablabla, поэтому я включил его, как вы его видите сейчас, в одной строке перед удаленным атрибутом. Спасибо за вашу помощь - person Reft; 05.02.2014
comment
Глядя на URL-адрес /Account/Login?ReturnUrl=%2fAccount%2fIsEmailAvailable%3fEmail%3dmyslex%2540gmai‌​l.com&Email=myslex%40gmail.com, может быть, ваш метод проверки находится в контроллере, который требует аутентификации пользователей? Поскольку ответ перенаправляет пользователей на страницу входа... - person Daniel J.G.; 05.02.2014
comment
Когда я пытаюсь зарегистрировать нового пользователя и вкладку из текстового поля электронной почты, он никогда не достигает метода действия в отладчике. - person Reft; 05.02.2014
comment
Вот что я имею в виду, если этот метод проверки находится в контроллере с атрибутом [Authorize] (или если фильтр был зарегистрирован глобально...), он никогда не достигнет этого метода, пока пользователь не будет аутентифицирован первым - person Daniel J.G.; 05.02.2014

Вы можете настроить действие контроллера MVC и использовать jquery для запроса его на лету. Вот статья, в которой объясняются способы сделать это (имейте в виду, что это для текстового поля с автозаполнением, но теория та же): Как создать текстовое поле с автозаполнением?

Мне было бы очень интересно увидеть решение, которое вы придумали для выполнения этой задачи.

person FrankO    schedule 05.02.2014