【问题标题】:Ajax.BeginForm with BeforeSendAjax.BeginForm 与 BeforeSend
【发布时间】:2014-03-21 21:54:24
【问题描述】:

我的 MVC 网站上有几个 Ajax.BeginForm。同时我需要处理我的 Ajax 调用的 beforeSend 事件。

所以下面的代码适用于我的手动 jquery ajax 调用,但它不适用于 Ajax.BeginForm 助手:

$.ajaxSetup({
    'beforeSend': function (xhr) {
        alert('');
    }
});

有没有办法处理 MVC Ajax.BeginForm 上的 beforeSend 事件?

-------------------------------------------编辑 -------------------------------------

我需要 before send 事件,因为我想更改请求标头:

'beforeSend': function (xhr) {
    securityToken = $('[name=__RequestVerificationToken]').val();
    xhr.setRequestHeader('__RequestVerificationToken', securityToken);
}

谢谢

【问题讨论】:

标签: javascript jquery ajax asp.net-mvc


【解决方案1】:

我认为您正在关注来自http://richiban.wordpress.com/2013/02/06/validating-net-mvc-4-anti-forgery-tokens-in-ajax-requests/ 的示例 这篇文章不涉及对 Ajax 表单集成的支持。我做了一些测试并找到了解决方案。

我假设您使用 MVC4 并引用了 jquery-1.9.1.jsjquery.validate.unobtrusive.jsjquery.unobtrusive-ajax.js

以下是我的代码

@model WebApplication1.Models.DummyModel

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <script src="~/Scripts/jquery-1.9.1.js"></script>
    <script src="~/Scripts/jquery.validate.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
    <script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
</head>
<body>
    <div id="Parent"> 
        @using (Ajax.BeginForm(new AjaxOptions { HttpMethod = "post", OnBegin = "BeginClient" }))
        {
            @Html.AntiForgeryToken();
            <div>First Name</div><div>@Html.TextAreaFor(m => m.FirstName)</div>
            <div>Last Name</div><div>@Html.TextAreaFor(m => m.LastName)</div>
            <input type="submit" value="Submit" />
        }
    </div>
    <script type="text/javascript">
        function BeginClient(xhr) {
            alert("posting...");
            securityToken = $('[name=__RequestVerificationToken]').val();
            xhr.setRequestHeader('__RequestVerificationToken', securityToken);
        }
        $.ajaxSetup({
            'beforeSend': function (xhr) {
                securityToken = $('[name=__RequestVerificationToken]').val();
                alert(securityToken);
                xhr.setRequestHeader("__RequestVerificationToken", securityToken);
            }
        });
    </script>
</body>
</html>

基本上你需要利用onBegin事件,见http://johnculviner.com/ajax-beginform-ajaxoptions-custom-arguments-for-oncomplete-onsuccess-onfailure-and-onbegin/有清楚的解释每个事件的参数是什么。

然后在你的全局属性类中,你的代码看起来像

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class ValidateAntiForgeryTokenOnAllPostsAttribute : AuthorizeAttribute
{
    /// <summary>
    /// Executes authorization based on anti-forge token.
    /// </summary>
    /// <param name="filterContext">MVC pipeline filter context.</param>
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var request = filterContext.HttpContext.Request;

        // Only validate POSTs
        if (request.HttpMethod == WebRequestMethods.Http.Post)
        {
            // Ajax POSTs and normal form posts have to be treated differently when it comes to validating the AntiForgeryToken
            if (request.IsAjaxRequest())
            {
                var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];

                var cookieValue = antiForgeryCookie != null
                    ? antiForgeryCookie.Value
                    : null;

                AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
            }
            else
            {
                new ValidateAntiForgeryTokenAttribute().OnAuthorization(filterContext);
            }
        }
    }
}

通过这种方式,您仍然可以强制使用 Ajax 表单的防伪令牌。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    对于Ajax.BeginForm,您可以使用AjaxOptions.OnBegin

    @using (Ajax.BeginForm("actionName", "controllerName", new AjaxOptions() {
                OnBegin = "requestBeginHandler"})) {
        ...markup here...
    }
    

    更新。要添加新的请求标头,您可以执行以下操作:

    function requestBeginHandler(ajaxContext) { 
        var request = ajaxCOntext.get_request();
        securityToken = $('[name=__RequestVerificationToken]').val();
        request.get_headers()['__RequestVerificationToken'] = securityToken;
    }
    

    【讨论】:

    • 发送前和 OnBegin 一样吗?因为我需要之前的更改来更新请求标头。看看我的问题编辑。谢谢
    • @hugohilario,不,这些是不同的功能。在意识到您的目的是什么后,我删除了重构建议。您仍然可以访问请求对象并添加标头 - 使用可能的解决方案更新帖子。虽然它没有经过测试,所以可能需要一些努力才能使其工作
    • 我正在测试你的代码,但是ajaxContext的参数是什么?
    • @hugohilario,这是在MicrosoftMvcAjax.js 库中定义的Sys.Mvc.AjaxContext 类型的对象。它作为参数传递给AjaxOptions 客户端函数,并允许读取和操作ajax 请求和响应。将其视为 XMLHttpRequest 的一种包装器
    猜你喜欢
    • 1970-01-01
    • 2014-08-01
    • 1970-01-01
    • 2012-09-26
    • 2013-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-15
    相关资源
    最近更新 更多