【问题标题】:Controller method that does not return any view不返回任何视图的控制器方法
【发布时间】:2012-03-23 14:37:49
【问题描述】:

如何更改此方法以检查登录名和密码,并且在此之后不刷新日志表单所在的整个页面(日志表单在 jQuery 对话框中)。此方法不应将我重定向到 /Home/Index 或刷新整个页面。应该让我登录,然后 jQuery 脚本应该关闭对话窗口。

AccountController:

[HttpPost]
    public ActionResult LogOnDialogForm(LogOnModel model, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            if (Membership.ValidateUser(model.UserName, model.Password))
            {
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                    && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                {
                    return Redirect(returnUrl);
                }
                else
                {
                    return RedirectToAction("Index", "Home");
                }
            }
            else
            {
                ModelState.AddModelError("", "The user name or password provided is incorrect.");
            }
        }

        // If we got this far, something failed, redisplay form
        return View("LogOn");
    }

视图中的 jQuery 脚本(我有打开对话框的登录按钮):

<script>
$(function () {
    $("#dialog:ui-dialog").dialog("destroy");

    var name = $("#name"),
        password = $("#password"),
        allFields = $([]).add(name).add(password),
        tips = $(".validateTips");

    function updateTips(t) {
        tips
            .text(t)
            .addClass("ui-state-highlight");
        setTimeout(function () {
            tips.removeClass("ui-state-highlight", 500);
        }, 500);
    }

    function checkLength(o, n, min, max) {
        if (o.val().length > max || o.val().length < min) {
            o.addClass("ui-state-error");
            updateTips("Length of " + n + " must be between " +
                min + " and " + max + ".");
            return false;
        } else {
            return true;
        }
    }

    $("#dialog-form").dialog({
        autoOpen: false,
        height: 380,
        width: 350,
        modal: true,
        buttons: {
            "Login": function () {
                var form = $('form', this);
                $(form).submit();
                $(this).dialog("close");
            },
            Cancel: function () {
                $(this).dialog("close");
            }
        },
        close: function () {
            allFields.val("").removeClass("ui-state-error");
        }
    });

    $("#login")
        .button()
        .click(function () {
            $("#dialog-form").dialog("open");
        });
});
</script>

包含表单主体的视图:

    @model BlogNet.Models.LogOnModel

<p>
    @Html.ActionLink("Register", "Register") if you don't have an account.
</p>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.")

@using (Html.BeginForm("LogOnDialogForm", "Account", FormMethod.Post, new { @class = "dialogForm"}))
{
    <div>
        <fieldset>
            <div class="editor-label">
                @Html.LabelFor(m => m.UserName)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(m => m.UserName)
                @Html.ValidationMessageFor(m => m.UserName)
            </div>

            <div class="editor-label">
                @Html.LabelFor(m => m.Password)
            </div>
            <div class="editor-field">
                @Html.PasswordFor(m => m.Password)
                @Html.ValidationMessageFor(m => m.Password)
            </div>

            <div class="editor-label">
                @Html.CheckBoxFor(m => m.RememberMe)
                @Html.LabelFor(m => m.RememberMe)
            </div>
        </fieldset>
    </div>
}

【问题讨论】:

    标签: jquery asp.net asp.net-mvc-3 jquery-ui razor


    【解决方案1】:

    您需要对您的登录表单进行 AJAX 化。现在它是一个标准的 HTML &lt;form&gt;,它在提交时会将输入字段 POST 到服务器并刷新整个页面。

    所以:

    "Login": function () {
        var dialog = this;
        var form = $('form', dialog);
        $.ajax({
            url: form.attr('action'),
            type: form.attr('method'),
            data: form.serialize(),
            success: function(result) {
                if (result.success) {
                    // authentication was successful 
                    // Here you can close the dialog, redirect, refresh
                    // some part of the DOM, whatever you want
                    $(dialog).dialog("close");
                } else {
                    // an error occurred => we refresh the dialog:
                    $('#dialog-form').html(result);
                }
            }
        });
    }
    

    您还应该修改您的控制器操作,以便在成功验证的情况下它只返回 JSON 而不是重定向:

    if (Membership.ValidateUser(model.UserName, model.Password))
    {
        FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
        if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
            && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
        {
            return Json(new { success = true, returnUrl = returnUrl });
        }
        else
        {
            return Json(new { success = true, returnUrl = Url.Action("Index", "Home") });
        }
    }
    

    【讨论】:

    • 与我的类似,但由于该方法实际上没有失败,所以操作方法上的失败不会仍然命中success吗?
    • @hunter,是的,绝对的。只是您需要区分身份验证成功的情况和例如用户输入错误密码的情况。在第二种情况下,您可能希望在对话框中向他显示​​一些错误消息,通知他。
    【解决方案2】:

    尝试更改代码的 Login 部分:

    "Login": function () {
        var form = $("form", this);
        $.post(form.attr("action"), form.serialize(), function(data) {            
            if ($(data).find(".validation-summary").length > 0)
            {
                $("#dialog-form").html(data);
            }
            else { $(this).dialog("close"); }
        });
    },
    

    【讨论】:

    • 成功返回模型时似乎有点沉重,但我喜欢这样一个事实,即它可以让您重用相同的操作/视图,无论是否在对话框中
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多