我和这里的用户有相似之处: ASP.NET MVC 3.0 WebGrid - Ajax Enabled 和这里: http ://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/22be0501-1b0b-496a- 9d0c-f9f5138996ac
但是,这些线程中的任何建议都没有帮助。
具体细节:当在我的 Windows 7/IIS 8 机器上的本地调试器中运行时,在 ajax 回发尝试更新后,我收到“A jQuery script reference is required in order to enable Ajax support in the "WebGrid" helper”消息. 但是,相同的代码不会在 FF 中或在针对服务器上运行的相同代码版本(IIS 6)使用 IE 时导致问题。更令人困惑的是,当我第一次编写这段代码时,我从来没有遇到过这个问题——它只是最近才开始抛出错误。
发生错误时,“正确”更新的内容会在整个页面重定向到仅部分视图并在屏幕上弹出弹出窗口之前在屏幕上闪烁。就好像它工作正常,但随后会重置它并导致它停止使用 ajax。
为了尝试排除故障,我将 jquery 的 .min 版本替换为完整版本并逐步执行代码。在调试器中,由于全局 ajax 计数器中的值,jQuery 的行为不同并触发“ajaxStop”。当我在同一个 IE 浏览器中针对相同代码的服务器版本运行外部脚本调试器时,这似乎不会发生(尽管我在服务器上仍然有“最小”版本,所以无法准确查看)。正是这个 ajaxStop 似乎迫使 webgrid 认为 jQuery 没有加载到页面上,并且不会让 ajax 行为“粘住” - 强制只加载部分视图的新页面。
我的页面不是很简单:主视图有几个包含部分视图的 div - divSearch 包含调用 ajax 回发的搜索部分视图,而 divList 包含需要根据搜索结果更新的网格。搜索部分视图调用的控制器方法将搜索结果的“新”内容呈现为字符串,并将它们作为 JsonResult 的一部分发送回,然后通过 jQuery 将其分配给 divList 的 html。(我在应用程序的几个地方使用了这种技术,并且我已经验证了返回的字符串是局部视图的正确内容)。
jQuery(以及所有其他 js 包括)位于布局页面的顶部,并在任何部分视图之前呈现。
主视图:
@model WebUI.Areas.Admin.Models.Client.ManageClientsModel
@{
ViewBag.Title = "ManageClients";
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
<style type="text/css">
.inv
{
visibility: hidden;
}
.vis
{
visibility: visible;
}
</style>
<h2>ManageClients</h2>
<div id="divSearch">
@Html.Partial("_ClientSearch", Model.ClientList)
</div>
<div id="divList">
@Html.Partial("_ClientList", Model.ClientList)
</div>
<br/>
<div id="newSection">
<div id="divEdit"> <button class="toggleNew">
Add Client
</button>
</div>
div class="inv" id="divNew"> @Html.Partial("_Create", Model.ClientVM ) </div>
</div>
<script type="text/javascript">
$(function () {
$(".toggleNew").click(function () {
$("#divNew").toggleClass("inv");
return false;
});
});
</script>
客户搜索部分:
@using Core.Entities
@model WebUI.Areas.Admin.Models.Client.ClientListViewModel
<div id="clientSearch">
<form action="@Url.Action("JsonSearch","Client", new { area = "Admin"})"
onsubmit="return formSearchSubmit(this);" >
<div class="divReturnErrors"></div>
@if(TempData["SearchName"] == null)
{
TempData["SearchName"] = Model.SearchName;
}
<br/>
@Html.LabelFor(model => model.SearchName, "Search for client name:")
@Html.EditorFor(model => model.SearchName)
<input type="submit" value="Search" name="btnSearch" />
</form>
</div>
<script type="text/javascript">
function formSearchSubmit(formToSubmit) {
//this line submits the form data to the JsonSearch method
$.post($(formToSubmit).attr("action"),
{ SearchName: $(formToSubmit).find("#SearchName").val() },
function (data) { //this is the callback from JsonSearch
// that handles the results.
if (data["IsSuccess"] == undefined || data["IsSuccess"] == false)
$('div.divReturnErrors').html(data["Errors"]);
//put errors in divReturnErrors
else { //if it succeeds we stuff the string containing the
//partial view into the _ClientList control's div to
//replace previous grid.
$("#divList").html(data["PartialViewHtml"]);
}
}, "json");
return false;
}
</script>
客户列表部分视图
@model WebUI.Areas.Admin.Models.Client.ClientListViewModel
<h2>Clients</h2>
@helper TrueFalseToYesNo(bool val) {
if (val)
{
<span>Yes</span>
}
else
{
<span>No</span>
}
}
<div id="clientListing">
@{
if(Model.SearchName != null)
{
TempData["SearchName"] = Model.SearchName;
}
var grid = new WebGrid<NeedleFinder.Core.Entities.Client>(null, rowsPerPage: 10,
canSort: false, defaultSort: "ClientName",
ajaxUpdateContainerId:"clientListing");
grid.Bind(Model.Clients, rowCount: Model.TotalRows, autoSortAndPage: false);
@grid.GetHtml(htmlAttributes: new {id= "clientListing"},
tableStyle: "table90",
alternatingRowStyle: "duncanTableAltRows",
headerStyle: "duncanTableHeaders",
columns: grid.Columns(
grid.Column(columnName: "Client ID", style: "logcolumn",
format: item =>
@Ajax.ActionLink(((object)item.ClientID).ToString(),
Model.LinkAction, new { id = item.ClientID }, new AjaxOptions {
HttpMethod = "GET", UpdateTargetId = "divEdit", InsertionMode =
InsertionMode.Replace })),
grid.Column(columnName: "ClientName", style: "logcolumn"),
grid.Column(columnName: "Abbreviation", style: "logcolumn"),
//grid.Column(columnName: "IsActive", style: "logcolumn")
grid.Column(columnName: "IsActive", style: "logcolumn",
format: item => @TrueFalseToYesNo(item.IsActive))
)
)
}
</div>
'错误'发生在这一行: $("#divList").html(data["PartialViewHtml"]); 从客户端搜索部分查看ajax回调函数。此行跳转到 jQuery 并在那里调用 ajaxStop。
请注意,我已经合并了来自其他线程的建议(jQuery 包括在顶部,将 webgrid 放在与 ajaxUpdateContainer 目标同名的 div 中,将 id 属性添加到同名的 webgrid 中。建议在 document.ready 中显式加载部分似乎不适用于我,因为我试图用基于输入的字符串填充这个 div,而不是简单地加载部分视图的默认“获取”版本。
这是页面第一次加载时呈现的 html(无论如何,当您执行 ajax 发布时它不会更新):(对于不稳定的格式表示歉意,但在每行添加 4 个缩进并没有真正干净地工作)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ManageClients</title>
<link href="/Content/Site.css" rel="stylesheet" type="text/css" />
<link href="/Content/themes/redmond/jquery-ui.css" rel="stylesheet" type="text/css" />
<script src="/Scripts/jquery-1.5.1.js" type="text/javascript"></script>
<script src="/Scripts/jquery-ui-1.8.18.js" type="text/javascript"></script>
<script src="/Scripts/jquery.unobtrusive-ajax.js" type="text/javascript"></script>
<script src="/Scripts/modernizr-1.7.js" type="text/javascript"></script>
<script src="/Scripts/jQuery.Validate.js" type="text/javascript"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js" type="text/javascript"></script>
</head>
<script type="text/javascript">
$(document).ready(function () {
$('.dateEditor').datepicker({ dateFormat: "mm/dd/yy" });
});
//This function should be called in your ajax post return are staying on same page
after success and/or you do have server side errors that couldn't have been found
//if there were still client side errors, otherwise you will still have the previous
validation errors.
function ClearValidationErrors() {
var container = $('form').find('[data-valmsg-summary="true"]');
var list = container.find('ul');
if (list && list.length) {
list.empty();
container.addClass('validation-summary-valid').removeClass('validation-summary-
errors');
}
}
</script>
<body>
<style type="text/css">
#topbar
{
background-color: Black;
margin: 0px;
padding: 5px;
}
#adminmenu_nav a
{
float: left;
width: 150px;
}
.logcolumn
{
padding-left: 10px;
padding-right: 10px;
border: 1px solid #BBBBBB;
}
</style>
<script>
$(function () {
$("#adminmenu_nav a").button();
$("#optionsPanel input").button();
$(".asButton input").button();
});
</script>
<div id="topbar">
<img style="margin-left:20px" src="/Content/Images/Logos/NFWhite.png"
alt="NeedleFinder" />
</div>
<div>
<div id="adminmenu_nav" style="float: left">
<table>
<tr><td><a href="/Admin/Client/ManageClients">Clients</a></td></tr>
<tr><td>Cases</td></tr>
<tr><td><a href="/Admin/User/ManageUsers">Users</a></td></tr>
<tr><td>Roles</td></tr>
<tr><td><a href="/Admin/Logging/Summary">Logs</a></td></tr>
</table>
</div>
<div style="overflow: hidden">
<span class="validation-summary-errors"></span>
<style type="text/css">
.inv
{
visibility: hidden;
}
.vis
{
visibility: visible;
}
</style>
<h2>ManageClients</h2>
<div id="divSearch">
<div id="clientSearch">
<form action="/Admin/Client/JsonSearch" onsubmit="return formSearchSubmit(this);" >
<div class="divReturnErrors"></div>
<br/>
<label for="SearchName">Search for client name:</label>
<input class="text-box single-line" id="SearchName" name="SearchName"
type="text" value="" />
<input type="submit" value="Search" name="btnSearch" />
</form>
</div>
<script type="text/javascript">
function formSearchSubmit(formToSubmit) {
//this line submits the form data to the JsonSearch method
$.post($(formToSubmit).attr("action"),
{ SearchName: $(formToSubmit).find("#SearchName").val() },
function (data) {
if (data["IsSuccess"] == undefined || data["IsSuccess"] == false)
$('div.divReturnErrors').html(data["Errors"]);
else
{
$("#divList").html(data["PartialViewHtml"]);
}
}, "json");
return false;
}
</script>
</div>
<div id="divList">
<h2>Clients</h2>
<div id="clientListing">
<script type="text/javascript">if (typeof(jQuery)=='undefined') alert("A jQuery script
reference is required in order to enable Ajax support in the \"WebGrid\" helper.");
</script><table class="table90" id="clientListing"><thead><tr
class="duncanTableHeaders"><th scope="col">Client ID</th><th
scope="col">ClientName</th><th scope="col">Abbreviation</th><th
scope="col">IsActive</th></tr></thead><tfoot><tr><td colspan="4">1 <a href="#"
onclick="$('#clientListing').load('/Admin/Client/ManageClients?page=2&
amp;__=634750282355486955 #clientListing');">2</a> <a href="#"
onclick="$('#clientListing').load('/Admin/Client/ManageClients?page=3&
amp;__=634750282355506956 #clientListing');">3</a> <a href="#"
onclick="$('#clientListing').load('/Admin/Client/ManageClients?page=4&
amp;__=634750282355516957 #clientListing');">4</a> <a href="#"
onclick="$('#clientListing').load('/Admin/Client/ManageClients?page=5&
amp;__=634750282355536958 #clientListing');">5</a> <a href="#"
onclick="$('#clientListing').load('/Admin/Client/ManageClients?page=2&
amp;__=634750282355546959 #clientListing');">></a> </td></tr></tfoot><tbody>
<tr><td class="logcolumn"><a data-ajax="true" data-ajax-method="GET" data-ajax-
mode="replace" data-ajax-update="#divEdit" href="/Admin/Client/_Edit/2042">2042</a>
</td><td class="logcolumn">ABC Legal</td><td class="logcolumn">ABC123</td><td
class="logcolumn"> <span>Yes</span>
</td></tr><tr class="duncanTableAltRows"><td class="logcolumn"><a data-ajax="true"
data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#divEdit"
href="/Admin/Client/_Edit/2044">2044</a></td><td class="logcolumn">ABC Legal
3</td><td class="logcolumn">ABC125</td><td class="logcolumn">
<span>Yes</span>
</td></tr><tr><td class="logcolumn"><a data-ajax="true" data-ajax-method="GET"
data-ajax-mode="replace" data-ajax-update="#divEdit" href="/Admin/Client/_Edit
/2045">2045</a></td><td class="logcolumn">ABC Legal 4b</td><td
class="logcolumn">ABC4bb</td><td class="logcolumn"> <span>Yes</span>
</td></tr><tr class="duncanTableAltRows"><td class="logcolumn"><a data-ajax="true"
data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#divEdit"
href="/Admin/Client/_Edit/2047">2047</a></td><td class="logcolumn">ABC Legal
6</td><td class="logcolumn">ABC6</td><td class="logcolumn"> <span>No</span>
</td></tr><tr><td class="logcolumn"><a data-ajax="true" data-ajax-method="GET"
data-ajax-mode="replace" data-ajax-update="#divEdit" href="/Admin/Client/_Edit
/2048">2048</a></td><td class="logcolumn">ABC Legal 7</td><td
class="logcolumn">ABC7</td><td class="logcolumn"> <span>Yes</span>
</td></tr><tr class="duncanTableAltRows"><td class="logcolumn"><a data-ajax="true"
data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#divEdit"
href="/Admin/Client/_Edit/2049">2049</a></td><td class="logcolumn">ABC Legal
8a</td><td class="logcolumn">ABC8a</td><td class="logcolumn">
<span>Yes</span>
</td></tr><tr><td class="logcolumn"><a data-ajax="true" data-ajax-method="GET"
data-ajax-mode="replace" data-ajax-update="#divEdit" href="/Admin/Client/_Edit
/2050">2050</a></td><td class="logcolumn">ABC Legal 9</td><td
class="logcolumn">ABC9</td><td class="logcolumn"> <span>Yes</span>
</td></tr><tr class="duncanTableAltRows"><td class="logcolumn"><a data-ajax="true"
data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#divEdit"
href="/Admin/Client/_Edit/2043">2043</a></td><td class="logcolumn">ABC
Legal2</td><td class="logcolumn">ABC124</td><td class="logcolumn">
<span>Yes</span>
</td></tr><tr><td class="logcolumn"><a data-ajax="true" data-ajax-method="GET"
data-ajax-mode="replace" data-ajax-update="#divEdit" href="/Admin/Client/_Edit
/2046">2046</a></td><td class="logcolumn">ABC Legal5</td><td
class="logcolumn">ABC5</td><td class="logcolumn"> <span>Yes</span>
</td></tr><tr class="duncanTableAltRows"><td class="logcolumn"><a data-ajax="true"
data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#divEdit"
href="/Admin/Client/_Edit/2051">2051</a></td><td class="logcolumn">ACE Legal
1</td><td class="logcolumn">ACE1</td><td class="logcolumn">
<span>Yes</span>
</td></tr></tbody></table></div>
</div>
<br/>
<div id="newSection">
<div id="divEdit"> <button class="toggleNew">
Add Client
</button></div><!-- placeholder for _Edit., will replace button when editing//-->
<div class="inv" id="divNew">
<form action="/Admin/Client/JsonCreate" onsubmit="return formCreateSubmit(this);">
<div>
<div class="titleText">Add Client</div>
<div class="divClientSideVal">
<div class="validation-summary-valid" data-valmsg-summary="true"><ul><li
style="display:none"></li>
</ul></div>
</div>
<div class="divCreateErrors"></div>
<fieldset>
<table>
<tr>
<td>
<label for="CurrentClient_ClientName">Name</label>
</td>
<td><input data-val="true" data-val-length="Client Name must be 50
characters or fewer" data-val-length-max="50" data-val-
required="Client Name is required."
id="CurrentClient_ClientName" name="CurrentClient.ClientName"
style="width: 120px;" type="text" value="" />
</td>
<td><span class="field-validation-valid" data-valmsg-
for="CurrentClient.ClientName" data-valmsg-replace="false">*</span></td>
</tr>
<tr>
<td>
<label for="CurrentClient_Abbreviation">Abbreviation</label>
</td>
<td><input data-val="true" data-val-length="Abbreviation must be 6
characters or fewer" data-val-length-max="6" data-val-
required="Abbreviation is required." id="CurrentClient_Abbreviation"
name="CurrentClient.Abbreviation" style="width: 120px;" type="text"
value="" />
</td>
<td><span class="field-validation-valid" data-valmsg-
for="CurrentClient.ClientName" data-valmsg-replace="false">*</span></td>
</tr>
<tr>
<td>
<label for="CurrentClient_IsActive">Is Active:</label>
</td>
<td>
<input data-val="true" data-val-required="The IsActive field is
required." id="CurrentClient_IsActive" name="CurrentClient.IsActive"
type="checkbox" value="true" /><input name="CurrentClient.IsActive"
type="hidden" value="false" />
</td>
</tr>
<tr>
<td>Enable for installations:</td>
<td>
<select Multiple="multiple" id="SelectedInstallations"
multiple="multiple" name="SelectedInstallations" style="width:
120px;">
<option value="1">Dev</option>
<option value="2">FakeDev</option>
</select>
</td>
</tr>
</table></fieldset>
<p>
<input type="submit" value="Create" name="btnCreate" />
</p>
</div>
</form>
<script type="text/javascript">
function formCreateSubmit(formToSubmit) {
var installations = "";
$('#SelectedInstallations option').each(function (i) {
if (this.selected == true) {
if (installations.length > 0) {
installations += ",";
}
installations += this.value;
}
});
//this line submits the form data to the JsonCreate method
$.post($(formToSubmit).attr("action"),
{ ClientName: $(formToSubmit).find("#CurrentClient_ClientName").val(),
Abbreviation:
$(formToSubmit).find("#CurrentClient_Abbreviation").val(),
IsActive:
$(formToSubmit).find("#CurrentClient_IsActive").is(':checked'),
SelectedInstallations: installations,
Action: "Create"
},
function (data) {
if (data["IsSuccess"] == undefined || data["IsSuccess"] == false)
{
if (data["Errors"] != undefined &&
data["Errors"].length > 0)
{
ClearValidationErrors();
('div.divCreateErrors').html(data["Errors"]);
} else {
$('div.divCreateErrors').html("");
}
} else {
window.location = "/Admin/Client/ManageClients";
}
}, "json");
return false;
}
</script> </div><!-- placeholder for _Create //-->
</div>
<script type="text/javascript">
$(function () {
$(".toggleNew").click(function () {
$("#divNew").toggleClass("inv");
return false;
});
});
</script>
</div>
</div>
<div class="InternalMenu"><a href="/Admin/Logging">Logging</a> - <a href="/Admin
/Client/ManageClients">Client</a></div>
</body>
</html>
任何建议都将不胜感激,因为我对导致问题的原因感到非常困惑。