Почему проверка не завершается ошибкой на стороне клиента, а не на стороне сервера?

Прямо сейчас у меня есть форма с несколькими полями, и при отправке я хочу проверить, занято ли имя пользователя или нет. Если принято, ничего не делать (показать ошибку проверки), если не принято, успешно перейти к следующей форме.

Вот что я сделал до сих пор:

Вид:

var RequestCreateAccount_Submit = function () {

        var res = false;
        ValidationAttribute.BlankValue(true);
        var form = $('form#RequestCreateAccount');
        $.validator.unobtrusive.parse(form);
        var res = form.valid();
        var data = form.serialize();

        if (res) {
            $.ajax({
                url: Url.getFullUrl('Account/RequestCreateAccount_Submit'),
                type: 'Post',
                data: data,
                cache:false,
                success: function (data) {
                    //Next Dialog

                },
                error: AjaxLog.HandleAjaxCallFail
            });
        }
        return res;
    }

Контроллер:

    [AllowAnonymous]
    [HttpPost]
    public ActionResult RequestCreateAccount_Submit(UserAccount userAccount)      
    {
        //Check if username is unique
        if (!WebSecurity.UserExists(userAccount.UserName))
        {
            UserSession.AddValue(StateName.CreateOrEditAccount, "CurrentUserAccount", userAccount);
            JsonResult res = Json(new { Success = true, data = "", Message = "" });
            return res;
        }
        JsonResult jres = Json(new { Success = false, data = "", Message = "Username is already registered"});
        return jres;
    }

Я протестировал его с известным именем пользователя, и он попал в строку success = false (за пределами оператора if) и не попал в статус if. Итак, я знаю, что проверка на стороне сервера работает.

Тем не менее, мне интересно, почему на стороне клиента все еще success = true, и появился следующий диалог. Он не потерпел неудачу при проверке. Что я делаю не так на стороне клиента?


person Kala J    schedule 25.06.2015    source источник
comment
О какой проверке мы говорим?   -  person haim770    schedule 25.06.2015
comment
Вы не показали нам, что в вашем клиентском коде должно гарантировать, что имя пользователя не используется. Как выглядит этот код?   -  person Becuzz    schedule 25.06.2015
comment
@Becuzz, у меня нет проверки имени пользователя на стороне клиента. Я хочу сказать, что проверка валидации на стороне сервера работает, но в коде на стороне клиента следующий диалог все еще отображается.   -  person Kala J    schedule 25.06.2015
comment
Почему вы просто не используете встроенный атрибут [Remote] и не спасаете себя написанием всего этого (плохого) скрипта? $.validator.unobtrusive.parse(form); бессмысленно. Назначение var data = form.serialize(); перед проверкой правильности формы - пустая трата времени.   -  person    schedule 26.06.2015
comment
@StephenMuecke, что должно вернуть мое действие для удаленной проверки? Должен ли он возвращать jsonresult или может возвращать bool? Спасибо.   -  person Kala J    schedule 26.06.2015
comment
в случае успеха return Json(true, JsonRequestBehavior.AllowGet); в противном случае return Json(false, JsonRequestBehavior.AllowGet); для отображения сообщения об ошибке, определенного в RemoteAttribute или Json("some error message", JsonRequestBehavior.AllowGet);, чтобы переопределить сообщение по умолчанию. См. Как: реализовать удаленную проверку в ASP.NET MVC < / а>   -  person    schedule 26.06.2015
comment
@StephenMuecke, я подумал об избежании удаленной проверки, потому что мне нужна только проверка на стороне сервера (из-за чувствительности имени пользователя), но, оказывается, мне все равно нужно отображать ошибку qtip, если имя пользователя уже существует, и для этого мне все еще нужен настраиваемый атрибут. Итак, я вернулся. Удаленная проверка - это в значительной степени проверка на стороне клиента, верно?   -  person Kala J    schedule 26.06.2015
comment
Да только его клиентская сторона. Лично я всегда реорганизую код до (скажем) метода private bool IsUnique(string userName), который я вызываю из метода удаленных атрибутов (для проверки на стороне клиента) и снова в методе POST (для защиты от злонамеренного пользователя)   -  person    schedule 26.06.2015
comment
На самом деле, только что заметил, что вы отправляете обратно всю модель (потому что, похоже, вы хотите добавить ее в сеанс), но [Remote] не позволит вам это сделать. Хотя в любом случае я не вижу необходимости делать это из вызова ajax - разве вам не нужно добавлять модель в сеанс в методе POST, если модель действительна?   -  person    schedule 26.06.2015
comment
@StephenMuecke, хм на самом деле. Я хотел бы поразмыслить над тем, как лучше всего подойти к этому сценарию с помощью пульта ДУ. Я хочу проверить имя пользователя при отправке формы. Это означает, что у меня есть отдельное действие для UserNameExists () и RequestCreateAccount_Submit (). Для Remote я бы использовал UserNameExists, который возвращает jsonresult, но как мне проверить это при отправке? То есть мне нужны два вызова ajax ... один для UserNameExists () и один для RequestCreateAccount_Submit () или ...?   -  person Kala J    schedule 26.06.2015


Ответы (2)


Причина в том, что ваш контроллер действительно успешно возвращает результат. Просто успешный результат указывает на ошибку. Хотя на данный момент они логически похожи, они очень разные. Ошибка будет зарезервирована для текущих исключений или сценариев 404 no route present.

Вы должны проверить статус ответа внутри вашей успешной функции обратного вызова

dotNetFiddle Demo

$.ajax({
  url: Url.getFullUrl('Account/RequestCreateAccount_Submit'),
  type: 'Post',
  data: data,
  cache:false,
  success: function (data) {
     if(data.Success === false){
         AjaxLog.HandleAjaxCallFail();
         // this may not make as much sense though
         // as the request didn't actually fail, just the action did
         //TODO: code for name fail
         return;//do not process next dialog
     }
     //Next Dialog

  },
  error: AjaxLog.HandleAjaxCallFail
  });
person Travis J    schedule 25.06.2015
comment
хм, хорошо, я попробую, но меня интересует одна вещь: проверка допустимости данных моей формы на стороне клиента мешает проверке подлинности имени пользователя на стороне сервера? Без прав? Правильно ли я настроил это выше? Спасибо. - person Kala J; 25.06.2015
comment
Нет, это не повлияет на серверную часть. Он просто анализирует элементы формы, для которых правильно установлены типы данных валидации, и проверяет, действительны ли они в соответствии с требованиями валидации для каждого элемента. Затем он сериализует их для отправки, чтобы связыватель модели мог принять данные. Ничто из этого не повлияет на вашу проверку на стороне сервера. - person Travis J; 25.06.2015
comment
Он все равно перешел к следующему диалогу: O Я последовал вашему подходу: if (data.success == False) {return;} // следующий - person Kala J; 25.06.2015
comment
Оппс, я имею в виду, что вернул успех с помощью Cap S. - person Kala J; 26.06.2015
comment
@KalaJ - Хм, возможно .Success не равно False и был неявно преобразован. В этом случае вы можете сравнить его с false, а не со строковым значением. - person Travis J; 26.06.2015
comment
Я заметил кое-что интересное при отладке: когда я возвращаю jres с Success = false, оператор AJAX if никогда не срабатывает. Это почему? - person Kala J; 26.06.2015
comment
@KalaJ - Что значит никогда не попадет? Он должен оценить, выполняется ли функция обратного вызова успеха. - person Travis J; 26.06.2015
comment
Я попытаюсь воспроизвести на dotNetFiddle, но он все равно перейдет к следующему диалогу. Я не уверен, почему? Я использую firebug, и он чертовски глючит, так что я не уверен, что это проблема с firebug или нет, но это не происходит внутри успеха: function (data) {} но тогда, если нет, почему он показывает следующий диалог? Хм - person Kala J; 26.06.2015
comment
меня огорчает :( Я не уверен, почему он переходит в следующий диалог @ _ @ - person Kala J; 26.06.2015
comment
А в dotNetFiddle это воспроизвести нельзя? Если вы используете console.log(data) и заглядываете в консоль firefox, как выглядят данные ответа? Кроме того, вы должны использовать хром: P - person Travis J; 26.06.2015
comment
Позвольте нам продолжить это обсуждение в чате. - person Kala J; 26.06.2015

success = false вашего объекта результата не означает, что запрос не выполнен. Это означает только data.success, не более того. Повторный запрос по-прежнему успешен (HTTP 200), что, на мой взгляд, является правильным кодом ответа. Если вы вернете код ошибки, например new HttpStatusCodeResult(404, "error message");, это означает, что ваш запрос не выполнен, но это не так.

Вы запрашиваете работы независимо от результата проверки. Так что вы можете проверить это в обратном вызове success вместо обратного вызова error:

success: function(data) {
    if (data.success) {
        //Next Dialog
    }
    else {
        // error message
    }
}
person DontVoteMeDown    schedule 25.06.2015
comment
Это не будет работать так, как написано. Имейте в виду, что когда сервер возвращает логическое значение, оно преобразуется в строковую форму. Таким образом, логическое значение true в C # на самом деле имеет значение True в ответе, а false - значение False. если (False) в JavaScript - это правда. - person Travis J; 25.06.2015
comment
@TravisJ Я знаю, это был только пример, иначе я бы вставил весь код, как вы. Может быть, если бы dataType: "json" был определен, это могло бы сработать. - person DontVoteMeDown; 25.06.2015
comment
Ах да, у него есть автоконвертер. Да, если бы вы использовали это, он преобразовал бы false в false. Хотя вам все равно нужно убедиться, что вы используете существующее свойство .Success, а не .success, которого нет. - person Travis J; 26.06.2015