Защо проверката не е неуспешна от страна на клиента, но е неуспешна от страна на сървъра?

В момента имам формуляр с няколко полета и при изпращане искам да проверя дали потребителското име е заето или не. Ако е взето, не правете нищо (покажете грешка при валидиране), ако не е взето, успешно продължете към следващия формуляр.

Ето какво съм направил досега:

Преглед:

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. Така че знам, че валидирането от страна на сървъра работи.

Чудя се обаче защо от страна на клиента все още е успех = вярно и се появява следващият диалогов прозорец. Не се провали при валидирането. Какво правя грешно от страна на клиента?


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
comment

Ако използвате Visual Studio Code, заменете

app.run(debug=True)

с

app.run()

Появява се, когато включването на вътрешния дебъгер деактивира дебъгера на VS Code.

  -  person Kala J    schedule 26.06.2015


Отговори (2)


Причината е, че вашият контролер наистина връща успешно резултат. Просто успешният резултат показва грешка. Макар и логически сходни в този момент, те са много различни. Грешката ще бъде запазена за действително хвърлени изключения или сценарии 404 без присъстващ маршрут.

Трябва да проверите за състоянието на отговора във вашата функция за обратно извикване за успех

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;} //next - person Kala J; 25.06.2015
comment
Упс, искам да кажа, че върнах Success с Cap S. - person Kala J; 26.06.2015
comment
@KalaJ - Хм, може би .Success не е равно на False и е имплицитно преобразуван. В който случай можете да го сравните с false за разлика от стойността на низа. - person Travis J; 26.06.2015
comment
Забелязах нещо интересно при отстраняване на грешки, когато върна jres с Success= false, командата if на AJAX никога не се удря. Защо така? - person Kala J; 26.06.2015
comment
@KalaJ - Какво искаш да кажеш никога не се удря? Той трябва да оцени дали функцията за обратно извикване за успех е изпълнена. - person Travis J; 26.06.2015
comment
Ще се опитам да репликирам в dotNetFiddle, но все още отива към следващия диалогов прозорец. Не съм сигурен защо? Използвам firebug и той е бъги по дяволите, така че не знам дали е проблем с firebug или не, но не влиза в успех: функция (данни) {}, но тогава, ако не, защо ще показва следващия диалогов прозорец? хмм - 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
Това няма да работи, както е написано. Имайте предвид, че когато сървърът върне булева стойност, тя се преобразува в низова форма. Така че boolean true в c# всъщност е True в отговора, а false е False. if(False) в JavaScript е true. - 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