我认为以下内容

@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>

这就是返回/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>

这在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"

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

最佳答案

发生这种情况的原因是因为WebGrid控件每次渲染时都会将以下脚本注入(inject)到DOM中(在这种情况下,每次提交AJAX表单都是因为WebGrid位于您要注入(inject)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>

该脚本包含在WebGrid帮助器中,一旦在WebGrid上启用AJAX,您将无法对它进行任何处理。在此脚本中,您无疑会注意到它如何以生动的方式订阅分页 anchor 的click事件:
$(containerId).parent().delegate(containerId + ' a[data-swhglnk="true"]', 'click', function() {
    $(containerId).swhgLoad($(this).attr('href'), containerId, callback);
    return false;
});

除了每次您单击提交按钮时,您都需要将此脚本注入(inject)到DOM中(因为您的WebGrid位于局部 View 中),并且基本上您多次订阅分页 anchor 的click事件,这一切都是甜蜜而花哨的。

如果此WebGrid帮助程序的作者让您可以用标准的delegate处理程序注册替换此click,那就太好了,在这种情况下,这将是理想选择,因为它不会创建多个事件注册,但是不幸的是,作者没有这样做并没有给您留下这种可能性。他们只是假设WebGrid将成为初始DOM的一部分,因此也是他们的脚本的一部分。

一种方法是订阅Ajax表单提交的OnBegin处理程序,并简单地 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>

但是老实说,我个人讨厌所有这些自动生成的脚本,并且根本不使用任何Ajax.*帮助器,也不在WebGrid上激活AJAX。我更喜欢使用jQuery轻松地AJAXify我想要的元素,这为我提供了对发生的事情的更好的控制。这样,我将把由WebGrid帮助程序自动生成的一堆JavaScript外部化为一个我将包含在View中的单独的js文件,并且不需要注销和清除创建的重复事件处理程序的困惑情况通过遵循标准的做事方式。

关于ajax - 从Ajax表单加载的MVC4 WebGrid-排序和分页时多次调用Controller,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22272273/

10-13 08:02