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

Затруднявам се в тази част от последните 3 дни. Имам страница _Layout, в която зареждам частичен изглед за влизане в модален div при щракване върху бутона за влизане. Когато изпратя, ако има валидации от страна на клиента, които ще работят добре и формулярът няма да бъде изпратен, докато не бъдат дадени правилните данни. Проблемът възниква, когато се извърши проверка от страна на сървъра. Ако идентификационните данни са невалидни, ще се пренасочи към същата страница, но модалното няма да се покаже. Когато щракна отново върху бутона за влизане, съобщението за грешка Невалидни идентификационни данни ще се покаже в модален режим. Искам да знам дали това е възможно по начина, по който се опитвам или има някакъв друг начин да го постигна.

Това е част от _Layout Page :

<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="/bg#" 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="/bg#">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 с истинска/невярна стойност за успех и незадължително съобщение.
  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="/bg#" 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