通过 ajax 添加局部视图

Adding partial view via ajax

在我的主布局中,我试图通过 ajax 添加登录部分视图,但我一直收到 'Internal Server Error'。我试过各种其他已发布的解决方案,但都没有成功

一切都很标准我有我的 HomeController 和 index.cshtml(它使用 layout.cshtml)

在布局中,文档准备好后,我使用 ajax 查看用户是否通过 HomeController 登录,如果返回值为 false,我想显示部分视图。

函数 showLoginPartial 尝试通过 ajax 从 LoginController 获取部分视图失败

"Error in showLoginPartial(): Internal Server Error :-: error"

我做错了什么?

HomeController 方法:

    public JsonResult IsUserLoggedIn()
    {
        return Json(new { result = (CurrentUser != null) }, JsonRequestBehavior.AllowGet);
    }

布局jquery:

$(document).ready(function () {
    checkLoggedIn();
    function checkLoggedIn() {
        $.ajax({
            url: '@Url.Action("IsUserLoggedIn", "Home", new { })',
            success: function (data) {
                if (data.result == false) {
                    //Show the login partial view
                    showLoginPartial();
                }
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                alert("Error in checkLoggedIn(): " + errorThrown + " :-: " + textStatus);
            }
        });
    }

    function showLoginPartial() {
        $.ajax({
            url: '@Url.Action("LoginDisplay", "Login", new { })',
            success: function (response) {
                //add the partial view after #ib-container div
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                //Error displays
                alert("Error in showLoginPartial(): " + errorThrown + " :-: " + textStatus);
            }
        });
    }
})

登录控制器:

public class LoginController : Controller
{
    // GET: Login
    [ChildActionOnly]
    public ActionResult LoginDisplay()
    {
        return PartialView("_LoginDisplay");
    }
    public JsonResult UserLoggedOut()
    {
        return Json(new { result = Nuclei.Models.CurrentUserAccount.Instance.LoggedOut }, JsonRequestBehavior.AllowGet);
    }

    public JsonResult UserAutoAuthenticate()
    {
        bool l_result = false;
        System.Threading.Thread.Sleep(3000);
        return Json(new { result = l_result }, JsonRequestBehavior.AllowGet);
    }

    public JsonResult UserManualAuthenticate()
    {
        bool l_result = false;
        System.Threading.Thread.Sleep(3000);
        return Json(new { result = l_result }, JsonRequestBehavior.AllowGet);
    }

    public JsonResult SendUserCredentials()
    {
        bool l_result = true;
        System.Threading.Thread.Sleep(3000);
        return Json(new { result = l_result }, JsonRequestBehavior.AllowGet);
    }
}

网站结构:

[编辑]

刚刚尝试通过 RenderAction() 添加局部视图并且成功了,但这不是我想要的,绝对想使用 ajax.

@{ Html.RenderAction("LoginDisplay", "Login"); }

也将其余方法添加到上面的 LoginController 中

_LoginDisplay.cshtml

<div id="login_layer_overlay">
</div>

<div id="login_layer">

    <div id="MainLoginDiv">
        <div id="LoginHeaderDiv" class="text-center">
            <h3 id="LoginHeader" class="page-header" style="color:white;">&nbsp;</h3>
        </div>
        <div id="Spinner" class="spinner">
            <i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
            <i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
            <i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
            <i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
            <i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
            <i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
            <i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
            <i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
            <i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
            <i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
        </div>
        <div id="ManualLogin" class="box" style="border: none;">
            @using (Html.BeginForm())
            {
                @Html.AntiForgeryToken()
                <div class="form-group">
                    <label class="control-label" style="color:white;">Username</label>
                    @Html.TextBox("username", null, new { id = "username", @class = "form-control", @Value="us" })
                </div>
                <div class="form-group">
                    <label class="control-label" style="color:white;">Password</label>
                    @Html.TextBox("password", null, new { id = "password", @class = "form-control", @Value = "pwd" })
                </div>
                <div class="text-center" style="margin-top:40px;">
                    <input type="button" id="ManualLoginBtn" value="Sign in" class="btn btn-primary" />
                    <br />
                    <input type="button" id="AutoLoginBtn" value="Auto Authenticate" class="btn btn-default" />
                    <input type="button" id="ForgotLoginBtn" value="Forgot Credentials" class="btn btn-default" />
                </div>
            }
        </div>
        <div id="ForgotLogin" class="box" style="border: none;">
            @using (Html.BeginForm())
            {
                @Html.AntiForgeryToken()
                <div class="form-group">
                    <label class="control-label" style="color:white;">Email</label>
                    @Html.TextBox("email", null, new { id = "email", @class = "form-control", @Value = "jhjhblah" })
                </div>
                <div class="text-center" style="margin-top:40px;">
                    <input type="button" id="BackToLoginBtn" value="Back" class="btn btn-default" />
                    <input type="button" id="ForgotSubmitBtn" value="Submit" class="btn btn-primary" />
                </div>
            }
        </div>
    </div>
</div>
<script>
    $(document).ready(function () {

        var spinnerItems = $("#Spinner i b");
        $("#MainLoginDiv").css("opacity", "1");
        checkUserLoggedOut();


        function checkUserLoggedOut() {
            $.ajax({
                //First need to check for logged off
                url: '@Url.Action("UserLoggedOut", "Login", new { })',
                success: function (data) {

                    if (data.result == false) {
                        showAutoAuthenticate();
                    }
                    else {
                        showManualForm();
                    }
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    alert("Error: " + errorThrown + " :-: " + textStatus);
                }
            });
        }

        function showAutoAuthenticate() {
            $("#LoginHeader").text("Auto Authenticating");
            $("#ManualLogin").css("opacity", "0");
            setTimeout(function () { $("#ManualLogin").css("display", "none"); }, 550);
            $("#Spinner").css("opacity", "1");

            spinnerItems.each(function () {
                $(this).addClass("spinAnimation");
            })
            $.ajax({
                url: '@Url.Action("UserAutoAuthenticate", "Login", new { })',
                success: function (data) {

                    if (data.result == false) {
                        //Switch to manual
                        //showForgotLogin();
                        showManualForm();
                    }
                    else {
                        //Remove login
                        $("#AutoLogin").css("opacity", "0");
                        spinnerItems.each(function () {
                            $(this).removeClass("spinAnimation");
                        })
                    }
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    alert("Error in showAutoAuthenticate(): " + errorThrown + " :-: " + textStatus);
                }
            });
        }

        function showManualAuthenticate() {
            $("#LoginHeader").text("Authenticating");
            $("#ManualLogin").css("opacity", "0");
            setTimeout(function () { $("#ManualLogin").css("display", "none"); }, 550);
            $("#Spinner").css("opacity", "1");

            spinnerItems.each(function () {
                $(this).addClass("spinAnimation");
            })

            $.ajax({
                url: '@Url.Action("UserManualAuthenticate", "Login", new { })',
                success: function (data) {

                    if (data.result == false) {
                        //Switch to manual
                        //showForgotLogin();
                        showManualForm();
                    }
                    else {
                        //Remove login
                        $("#AutoLogin").css("opacity", "0");
                        spinnerItems.each(function () {
                            $(this).removeClass("spinAnimation");
                        })
                    }
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    alert("Error in showManualAuthenticate(): " + errorThrown + " :-: " + textStatus);
                }
            });
        }

        function showForgottenProcessing() {
            $("#ForgotLogin").css("opacity", "0");
            setTimeout(function () { $("#ForgotLogin").css("display", "none"); }, 550);
            $("#Spinner").css("opacity", "1");

            spinnerItems.each(function () {
                $(this).addClass("spinAnimation");
            })

            $.ajax({
                url: '@Url.Action("SendUserCredentials", "Login", new { })',
                success: function (data) {

                    if (data.result == false) {
                        //Switch to manual
                        showForgotLoginForm();
                    }
                    else {
                        //Go back to login
                        showManualForm();
                    }
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    alert("Error in showManualAuthenticate(): " + errorThrown + " :-: " + textStatus);
                }
            });
        }

        function showManualForm() {

            $("#Spinner").css("opacity", "0");
            spinnerItems.each(function () {
                $(this).removeClass("spinAnimation");
            })
            $("#ForgotLogin").css("opacity", "0");
            setTimeout(function () { $("#ForgotLogin").css("display", "none"); }, 550);

            $("#LoginHeader").text("Login");
            $("#ManualLogin").css("display", "block");
            $("#ManualLogin").css("opacity", "1");
        }

        function showForgotLoginForm() {

            $("#Spinner").css("opacity", "0");
            spinnerItems.each(function () {
                $(this).removeClass("spinAnimation");
            })
            $("#ManualLogin").css("opacity", "0");
            setTimeout(function () { $("#ManualLogin").css("display", "none"); }, 550);

            $("#LoginHeader").text("Retrieve Credentials");
            $("#ForgotLogin").css("display", "block");
            $("#ForgotLogin").css("opacity", "1");
        }

        $("#AutoLoginBtn").click(function () {
            showAutoAuthenticate();
        });
        $("#ForgotLoginBtn").click(function () {
            showForgotLoginForm();
        });
        $("#BackToLoginBtn").click(function () {
            showManualForm();
        });
        $("#ManualLoginBtn").click(function () {
            showManualAuthenticate();
        });
        $("#ForgotSubmitBtn").click(function () {
            showForgottenProcessing();
        });
    })
</script>

[ChildActionOnly] 属性用法确保操作方法只能作为父视图的子方法调用(即禁用直接导航以加载部分视图,如 /Login/LoginDisplay),并且通常使用使用 RenderAction() 助手渲染部分视图:

Any method that is marked with ChildActionOnlyAttribute can be called only with the Action or RenderAction HTML extension methods.

由于您不是通过 RenderAction() 调用局部视图,而是使用 AJAX 调用 url 设置中的直接 URL 导航,因此 ChildActionOnlyAttribute立即阻止响应该 URL 的请求和运行时错误 只能由子请求访问的子操作 将被抛出(在 AJAX 中显示为 "Internal Server Error"结果)。

因此,控制器操作不应使用 [ChildActionOnly] 属性:

[HttpGet]
public ActionResult LoginDisplay()
{
    return PartialView("_LoginDisplay");
}

而 AJAX 调用应该是这样的:

function showLoginPartial() {
    $.ajax({
        url: '@Url.Action("LoginDisplay", "Login")',
        type: 'GET',
        success: function (response) {
            $('#ib-container').html(response);
        },
        error: function (XMLHttpRequest, textStatus, errorThrown) {
           //Error displays
           alert("Error in showLoginPartial(): " + errorThrown + " :-: " + textStatus);
        }
    });
}

参考文献:

System.Web.Mvc.ChildActionOnlyAttribute Class

Using ChildActionOnly in MVC