1

我和这里的用户有相似之处: 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="$(&#39;#clientListing&#39;).load(&#39;/Admin/Client/ManageClients?page=2&
  amp;__=634750282355486955 #clientListing&#39;);">2</a> <a href="#" 
  onclick="$(&#39;#clientListing&#39;).load(&#39;/Admin/Client/ManageClients?page=3&
  amp;__=634750282355506956 #clientListing&#39;);">3</a> <a href="#" 
  onclick="$(&#39;#clientListing&#39;).load(&#39;/Admin/Client/ManageClients?page=4&
  amp;__=634750282355516957 #clientListing&#39;);">4</a> <a href="#" 
  onclick="$(&#39;#clientListing&#39;).load(&#39;/Admin/Client/ManageClients?page=5&
  amp;__=634750282355536958 #clientListing&#39;);">5</a> <a href="#" 
  onclick="$(&#39;#clientListing&#39;).load(&#39;/Admin/Client/ManageClients?page=2& 
  amp;__=634750282355546959 #clientListing&#39;);">&gt;</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>

任何建议都将不胜感激,因为我对导致问题的原因感到非常困惑。

4

1 回答 1

0

好的 - 我发现了问题,所以我会报告。

这个问题实际上比与 jQuery 相关的更多是 MVC,但这是我如何将搜索表单放在一起的问题。

我将搜索按钮设置为 type=submit,并且还有一个 onsubmit 事件处理程序执行 ajax 回发。发生的事情是 ajax 回发正在做它应该做的事情,但是当它完成时,提交正在触发一个“get”,并且搜索表单的控制器中的“get”处理程序只返回一个 PartialViewResult --> 所以这是将屏幕内容替换为正常负载。由于部分视图没有包含包含的布局,因此引发了错误。

所以解决方法是 a) 将按钮类型更改为“button” b) 从表单声明中删除“onsubmit” c) 在表单中添加一个 id="frmSearch"(以便于选择性) d) 修改 formSearchSubmit 以采取来自 $("#frmSearch").action 的动作,而不是来自函数参数(这是一个按钮,而不是表单)的动作。

之后,它正确提交了 ajax 帖子并处理了返回更新,而不会触发表单的另一次提交。

于 2012-06-12T17:16:16.320 回答