Невозможно отобразить частичное представление в модальном режиме при получении ошибки на стороне сервера в MVC

Я борюсь с этой частью за последние 3 дня. У меня есть страница _Layout, на которой я загружаю частичное представление входа в модальный div при нажатии кнопки входа. Когда я отправляю, есть ли какие-либо проверки на стороне клиента, которые будут работать нормально, и форма не будет отправлена ​​​​до тех пор, пока не будут предоставлены правильные данные. Проблема возникает при проверке на стороне сервера. Если учетные данные недействительны, он будет перенаправлен на ту же страницу, но модальное окно отображаться не будет. Когда я еще раз нажму кнопку входа в систему, сообщение об ошибке Invalid Credentials будет отображаться в модальном режиме. Я хочу знать, возможно ли это так, как я пытаюсь, или есть ли другой способ добиться этого.

Это часть страницы _Layout :

<a class="btn btn-style btn-success btn-lg btn-wid" data-target="#modal" data-toggle="modal" id="flogin"> Login </a>

и модальный div на той же странице под нижним колонтитулом:

<div id="modal" class="modal">
    @{Html.RenderPartial("_Login", new Sample.Models.LoginModel());}
</div>

Вот представление _Login Partial:

@model Sample.Models.LoginModel
@section Validation {
    @Scripts.Render("~/bundles/jqueryval")
}

<section id="Login">

    @using (Html.BeginForm("Login", "Home", FormMethod.Post, new { enctype = "multipart/form-data", id = "LoginForm", ReturnUrl = ViewBag.ReturnUrl }))
    { 
        <div class="modal-content wrap col-md-4 col-xs-12 col-sm-12 col-md-offset-4">

            @Html.AntiForgeryToken()
            <div class="row">
                <button type="button" class="close" id="btnLoginModalClose" style="margin-top:-15px" data-dismiss="modal" aria-hidden="true">×</button>
            </div>

            <div class="row-fluid">
                <div id="LoginDialog" class="col-md-12">
                    <div class="modal-header">
                        <h3 id="login" class="modal-title">
                            Freshers Login
                        </h3>
                        <div class="ui-state-error-text">
                            @if (TempData["ModelState"] != null)
                            {
                                @TempData["ModelState"]
                            }

                        </div>
                    </div>

                    <div class="modal-body">
                        <div class="form-group">
                            <span class="ico-email"></span>
                            @Html.TextBoxFor(m => m.UserName, new { id = "floginEmail", placeholder = "Email", type = "email", @class = "input-lg ipt ip-email" })
                            <div class="text-danger">
                                @Html.ValidationMessageFor(model => model.UserName)
                            </div>
                        </div>
                        <div class="form-group">
                            <span class="ico-pwd"></span>
                            @Html.TextBoxFor(m => m.Password, new { id = "floginPassword", placeholder = "Password", type = "password", @class = "input-lg ipt ip-pwd" })

                            <a href="#" id="loginpswdshow" onclick="showhide($(this));"><span style="position:relative" id="sploginpswdshow" class="glyphicon glyphicon-eye-open show"></span></a>
                            <div class="text-danger">
                                @Html.ValidationMessageFor(model => model.Password)
                             </div>
                            </div>
                        <div class="form-group">

                            <div class="input-group">
                                <span class="input-group-addon">
                                    @Html.CheckBoxFor(m => m.RememberMe, new { id = "chkRemember", type = "checkbox", @class = "checkbox" })
                                </span>
                                @Html.LabelFor(m => m.RememberMe, new { @class = "form-control" })
                            </div><!-- /input-group -->
                        </div>
                    </div>
                    <div class="modal-footer" style="margin-top:14px">
                        <input type="submit" id="btnLogin" name="login" style="margin-top:-5px" class="btn btn-primary pull-left btn-flogin" value="Log-in" />
                        <div class="row-fluid">
                            <a class="text-center" style="font-size:medium" onclick="fresherForgotClick();" id="lnkForgot" href="#">Forgot password?</a>
                        </div>
                    </div>
                    <span class="text-info"><strong>Do not have an Account? <a class="btn alert-danger" id="btnCreateAccount">Click here to Create one!</a></strong></span>

                </div>
            </div>
        </div>
    }


</section>

и вот мой HomeController, который имеет результат _Login Post Action

public ActionResult Login(string redirect, Models.FreshersModel model)
        {
            if (model.IsValid(model.UserName,model.Password))
            {
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                if (!String.IsNullOrEmpty(redirect) || String.Compare(redirect, "none", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    if (redirect != null) Response.Redirect(redirect, true);
                }
                else
                {
                    return View("Index", "User");
                }
            }
            ModelState.AddModelError("", "Incorrect User Credentials");
            //ModelState.AddModelError("", "You entered an invalid password");
            TempData["ModelState"] = "Incorrect User Credentials";
            //return null;
            return RedirectToAction("Index", "Home");
        }

Пожалуйста, дайте мне знать, если это возможно сделать следующим образом.


person Guruprasad J Rao    schedule 07.09.2014    source источник


Ответы (1)


Ваш рабочий процесс, вероятно, должен следовать этому:

  1. Вместо обычной публикации формы используйте jQuery или аналогичный для асинхронной публикации формы.
  2. Верните JsonResult со значением успеха true/false и необязательным сообщением.
  3. Если значение успеха равно true, обновите страницу, в противном случае вставьте сообщение об ошибке в модальное окно.

Во-первых, измените действие входа в систему на что-то похожее на это:

public ActionResult Login(Models.FreshersModel model, string returnUrl)
{
    bool success = false;
    string message = "User name or password is incorrect.";

    if (ModelState.IsValid)
    {
        success = model.IsValid(model.UserName,model.Password);
        if(success)
        {
            message = string.Empty;
            FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
        }
    }

    return Json(new { success = success, message = message });
}

Во-вторых, я обрезал большую часть вашего модального окна до (почти) минимума, необходимого для работы модального плагина:

<div id="LoginDialog" class="modal hide">
    <div class="modal-header">
        <h3 id="login" class="modal-title">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
            Freshers Login
        </h3>
    </div>
    <div class="modal-body">
        @using (Html.BeginForm("Login", "Home", new { returnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { id = "LoginForm", role="form" }))
        { 
            @Html.AntiForgeryToken()

            <div id="errors" class="ui-state-error-text">
            </div>

            <div class="form-group">
                <span class="ico-email"></span>
                @Html.TextBoxFor(m => m.UserName, new { id = "floginEmail", placeholder = "Email", type = "email", @class = "input-lg ipt ip-email" })
                <div class="text-danger">
                    @Html.ValidationMessageFor(model => model.UserName)
                </div>
            </div>
            <div class="form-group">
                <span class="ico-pwd"></span>
                @Html.PasswordFor(m => m.Password, new { id = "floginPassword", placeholder = "Password", @class = "input-lg ipt ip-pwd" })
                <div class="text-danger">
                    @Html.ValidationMessageFor(model => model.Password)
                 </div>
                </div>
            <div class="form-group">
                <div class="input-group">
                    <span class="input-group-addon">
                        @Html.CheckBoxFor(m => m.RememberMe, new { id = "chkRemember", @class = "checkbox" })
                    </span>
                    @Html.LabelFor(m => m.RememberMe, new { @class = "form-control" })
                </div><!-- /input-group -->
            </div>
        }
    </div>
    <div class="modal-footer">
        <a href="#" class="btn">Close</a>
        <button type="button" class="btn btn-primary" id="btnLogin">Login</button>
    </div>
</div>

В-третьих, и последнее, добавьте в макет немного jQuery. Если вы хотите, вы можете обернуть это в условие Razor, чтобы оно вводилось в представление только в том случае, если пользователь не аутентифицирован.

$(function(){

    $(document)
        .on('submit', '#LoginForm', function(e) {   
            e.preventDefault(); /* we're taking over the default behaviour */

            var url = $(this).attr('action');
            var formData = $(this).serialize();

            $.post(url, formData)
                .fail(function(jqxhr, status, error){
                    $('#errors').html('An error occurred. Please try again.');
                })
                .done(function(response, status, jqxhr){
                    if(response.success) {
                        window.location.redirect('/');
                    }
                    else {
                        $('#errors').html(response.message);
                    }
                });
        })
        .on('click', '#btnSubmit', function(e) {
            e.preventDefault();
            $('#LoginForm').trigger('submit');
        });

});

Я пропустил некоторые части, например запуск модального окна, но это должно помочь вам начать работу.

person Tieson T.    schedule 07.09.2014
comment
Итак, вы говорите, что вместо ActionResult мне нужно использовать тип JsonResult.?? - person Guruprasad J Rao; 08.09.2014
comment
Если вы измените свой процесс для использования ajax, да. Вы можете оставить тип возвращаемого значения ActionResult, так как JsonResult неявно преобразует. - person Tieson T.; 08.09.2014
comment
Какой из них вы предлагаете, приятель...? Я имею в виду, что безопасно и не снижает производительность.?? - person Guruprasad J Rao; 08.09.2014
comment
В любом случае это не более и не менее безопасно. Производительность относительна. Я обновлю ответ, чтобы показать, что я предлагаю. - person Tieson T.; 08.09.2014