Пользовательская ошибка MVC AddModelError не отображается в форме Ajax - PullRequest
0 голосов
/ 09 октября 2018

У меня есть форма входа в систему, в которой я хотел бы показать пользовательскую ошибку, например «Пользователь не существует», так же, как работает ValidationMessageFor сообщения.

Я добавляю пользовательскую ошибку в контроллер, но онане отображается в форме.

Чтобы показать сообщения проверки в форме Ajax, я использовал технику возврата логина PartialView, который я возвращаю из контроллера

Спасибо за помощь!

Контроллер:

  [HttpPost]
        public ActionResult Login(Login login)
        {

            if (!ModelState.IsValid) //Check for validation errors
            {
                Response.StatusCode = (int)HttpStatusCode.BadRequest;
                return PartialView("_login", login);
            }

            ActiveDirectoryDAL.ADQueries ad = new ActiveDirectoryDAL.ADQueries();
            var userName = login.UserName.ToLower().Trim();
            var password = login.Password.Trim();


            var isValidUser = ad.Authenticate(userName, password);


            if (!isValidUser)
            {
                ModelState.AddModelError(string.Empty, "Login failed");
                return PartialView("_login", login);
            }

            FormsAuthentication.SetAuthCookie(login.UserName, false);
            return Json(new { RedirectUrl = Url.Action("Index", "Home") });

        }

Вид

@model PushNotificationWebSite.Models.Login
@{
    ViewBag.Title = "Login";
    Layout = "";
}


<html>
<head>
    <link href="~/Content/login.css" rel="stylesheet" />
    @Styles.Render("~/Content/bootstrap/css")
    @Scripts.Render("~/bundles/modernizr")
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
</head>
<script type="text/javascript">
    function OnSuccess(data) {
        if (data.RedirectUrl)
            window.location.href = data.RedirectUrl;
    }
    function OnLoginFailure(data) {
        debugger;
        $('#login').html(data.responseText);

    }
</script>

<body id="LoginForm">
    <div class="container">
        <h1 class="form-heading">login Form</h1>
        <div class="login-form">
            <div class="main-div">
                <div class="panel">
                    <h2>Admin Login</h2>
                    <p>Please enter your username and password</p>
                </div>
                @using (Ajax.BeginForm("Login", "Account", new AjaxOptions
                {
                    InsertionMode = InsertionMode.Replace,
                    HttpMethod = "POST",
                    LoadingElementId = "loader",
                    OnSuccess = "OnSuccess",
                    OnFailure = "OnLoginFailure"


                }, new { id = "login" }))
                {
                    @Html.ValidationSummary(true)
                    <div class="form-group">

                        @Html.TextBoxFor(model => model.UserName, new { @class = "form-control", autocomplete = "off", placeholder = "Username" })


                    </div>
                    <div class="form-group">

                        @Html.TextBoxFor(model => model.Password, new { @class = "form-control", autocomplete = "off", type = "password", placeholder = "Password" })
                        @Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" })

                    </div>

                    <button type="submit" class="btn btn-primary">Login</button>
                }
                <div id="loader" class="loader">
                    <img class="center" src="~/Images/ajax-loader.gif" />
                </div>
            </div>

        </div>
    </div>
</body>
</html>

Частичный вид:

@model PushNotificationWebSite.Models.Login

@using (Ajax.BeginForm("Login", "Account", new AjaxOptions
{
    HttpMethod = "POST",
    LoadingElementId = "loader",
    OnSuccess = "OnSuccess",
    OnFailure = "OnLoginFailure"


}, new { id = "login" }))
{
    @Html.ValidationSummary(true)
    <div class="form-group">

        @Html.TextBoxFor(model => model.UserName, new { @class = "form-control", autocomplete = "off", placeholder = "Username" })
        @Html.ValidationMessageFor(m => m.UserName, "", new { @class = "text-danger" })

    </div>
    <div class="form-group">

        @Html.TextBoxFor(model => model.Password, new { @class = "form-control", autocomplete = "off", type = "password", placeholder = "Password" })
        @Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" })

    </div>
    <button type="submit" class="btn btn-primary">Login</button>
}

Ответы [ 2 ]

0 голосов
/ 10 октября 2018

Я нашел основную причину.

Я забыл добавить Response.StatusCode = (int)HttpStatusCode.BadRequest;

перед отправкой return PartialView("_login", login); Сервер отправил резонанс OK 200, чтобы валидаторы не сработали

0 голосов
/ 10 октября 2018

Вместо использования string.Empty в качестве имени ключа вы можете назначить любую строку в качестве имени ключа для пользовательской ошибки ModelState.Измените ModelState.AddModelError() с этого:

ModelState.AddModelError(string.Empty, "Login failed");

на этот пример:

ModelState.AddModelError("LoginFailed", "Login failed");

Затем поместите вспомогательный элемент ValidationMessage в частичное представление с тем же именем ключа, которое назначено в ModelState.AddModelErrorкак пример ниже:

@* message without styling *@
@Html.ValidationMessage("LoginFailed")

@* message with styling *@
@Html.ValidationMessage("LoginFailed", new { @class = "text-danger" })

Или используйте ViewData.ModelState, чтобы отобразить его, снова с тем же именем ключа:

@ViewData.ModelState["LoginFailed"].Errors[0].ErrorMessage

Примечание:

В дополнение к настройке InsertionMode.Replace вы можете рассмотреть возможность использования UpdateTargetId для обновления содержимого формы частичного просмотра при сбое проверки:

@using (Ajax.BeginForm("Login", "Account", new AjaxOptions
{
    InsertionMode = InsertionMode.Replace,
    HttpMethod = "POST",
    LoadingElementId = "loader",
    UpdateTargetId = "elementId", // here you can set HTML element ID to update
    OnSuccess = "OnSuccess",
    OnFailure = "OnLoginFailure"
}, new { id = "login" }))
{
    // form contents
}
...