从Ajax表单加载的MVC4 WebGrid - 在排序和分页时多次调用Controller

gyo*_*fov 5 sorting ajax paging webgrid asp.net-mvc-4

我认为我有以下几点

@using (Ajax.BeginForm("Search", "Home", null,
                               new AjaxOptions
                                   {
                                       InsertionMode = InsertionMode.Replace,
                                       HttpMethod = "POST",
                                       UpdateTargetId = "gridContent",
                                   }, new { @class = "search" }))
{
    <input type="submit" value="Search" />
}
<div id="gridContent">
</div>
Run Code Online (Sandbox Code Playgroud)

这是返回/ Home/Search的内容

@model List<TestTable.Models.People>
@{
Layout = null;
}
@{
var grid = new WebGrid(Model, canPage: true, canSort: true, rowsPerPage: 5,             ajaxUpdateContainerId: "tableDiv"); grid.Pager(WebGridPagerModes.NextPrevious);
}
<div id="tableDiv">
    @grid.GetHtml(
        columns: grid.Columns(
        grid.Column("Name", " Name")
))
</div>
Run Code Online (Sandbox Code Playgroud)

这在MVC3中工作得很好,但MVC4会在每次新搜索时发送一个脚本,为每个分页和排序查询的每个提交按钮单击产生一个新的额外请求.以下是它的外观:

"http://localhost:59753/Home/Search".
"http://localhost:59753/Home/Search?sort=Name&sortdir=ASC&__swhg=1394297281115"
"http://localhost:59753/Home/Search". 
"http://localhost:59753/Home/Search?sort=Name&sortdir=ASC&__swhg=1394297284491"
"http://localhost:59753/Home/Search?sort=Name&sortdir=ASC&__swhg=1394297284490"
Run Code Online (Sandbox Code Playgroud)

任何想法如何解决?提前致谢!

Dar*_*rov 12

发生这种情况的原因是因为WebGrid控件每次渲染时都会将以下脚本注入到DOM中(在每次提交AJAX表单的情况下都是如此,因为WebGrid位于您在DOM中注入的部分中):

<script type="text/javascript">
    (function($) {
        $.fn.swhgLoad = function(url, containerId, callback) {
            url = url + (url.indexOf('?') == -1 ? '?' : '&') + '__swhg=' + new Date().getTime();

            $('<div/>').load(url + ' ' + containerId, function(data, status, xhr) {
                $containerId).replaceWith($(this).html());
                if (typeof(callback) === 'function') {
                    callback.apply(this, arguments);
                }
            });
            return this;
        }

        $(function() {
            $('table[data-swhgajax="true"],span[data-swhgajax="true"]').each(function() {
                var self = $(this);
                var containerId = '#' + self.data('swhgcontainer');
                var callback = getFunction(self.data('swhgcallback'));

                $(containerId).parent().delegate(containerId + ' a[data-swhglnk="true"]', 'click', function() {
                    $(containerId).swhgLoad($(this).attr('href'), containerId, callback);
                    return false;
                });
            })
        });

        function getFunction(code, argNames) {
            argNames = argNames || [];
            var fn = window, parts = (code || "").split(".");
            while (fn && parts.length) {
                fn = fn[parts.shift()];
            }
            if (typeof (fn) === "function") {
                return fn;
            }
            argNames.push(code);
            return Function.constructor.apply(null, argNames);
        }
    })(jQuery);
</script>
Run Code Online (Sandbox Code Playgroud)

这个脚本被封装到WebGrid帮助器中,一旦在WebGrid上启用AJAX,就没有太多可以对付它了.在这个脚本中,您无疑会注意到它如何click生动的方式订阅分页锚点的事件:

$(containerId).parent().delegate(containerId + ' a[data-swhglnk="true"]', 'click', function() {
    $(containerId).swhgLoad($(this).attr('href'), containerId, callback);
    return false;
});
Run Code Online (Sandbox Code Playgroud)

除了每次点击提交按钮,你将这个脚本注入你的DOM(因为你的WebGrid是部分的),并且基本上你click多次订阅分页锚点的事件时,这都是甜蜜和花花公子.

如果这个WebGrid帮助器的作者让你有可能delegate用标准的click处理程序注册来替换它本来是很好的,这在这种情况下是理想的,因为它不会创建多个事件注册,但不幸的是作者没有让你有这种可能性.他们只是假设WebGrid将成为初始DOM的一部分,因此也就是他们的脚本.

一种方法是订阅OnBeginAjax表单提交的处理程序和简单undelegate的现有事件处理程序,因为刷新DOM后它们将被覆盖:

@using (Ajax.BeginForm("Search", "Home", null,
    new AjaxOptions
    {
        InsertionMode = InsertionMode.Replace,
        OnBegin = "callback",
        HttpMethod = "POST",
        UpdateTargetId = "gridContent",
    }, new { @class = "search" }))
{
    <input type="submit" value="Search" />
}

<div id="gridContent"></div>

<script type="text/javascript">
    var callback = function (a) {
        $('#tableDiv').parent().undelegate('#tableDiv a[data-swhglnk="true"]', 'click');
    };
</script>
Run Code Online (Sandbox Code Playgroud)

但说实话,我个人只是讨厌所有这些自动生成的脚本,并且从不使用任何Ajax.*助手的东西以及在WebGrid上激活AJAX.我更喜欢使用jQuery不引人注意地AJAX化我想要的元素,这使我能够更好地控制正在发生的事情.这样我只需将WebGrid帮助器自动生成的一堆javascript外化到一个单独的js文件中,我将包含在我的View中,并且不需要注销和清理创建的重复事件处理程序的混乱遵循标准的做事方式.

  • @gyosifov nope,仍然破碎:( (2认同)