2017-03-06 64 views
5

我正在構建使用Visual Studio 2015的ASP.NET MVC 5應用程序。搜索在第一次嘗試時工作正常,但如果點擊頁面中的任何頁碼MVC PagedList component,它拋出一個Internal Server Error。這裏是AJAX表單;注意,從搜索接收到的數據傳送到一個局部視圖:在部分視圖中使用AJAX的ASP.NET MVC PagedList

@using (Ajax.BeginForm("SearchCustomers", "Permits", 
new AjaxOptions 
{ 
    UpdateTargetId = "targetElement", 
    OnSuccess = "onAjaxSuccess", 
    OnFailure = "onAjaxFailure" 
}, 
new { @class = "form-horizontal form-small", role = "form", id="customerSearchForm" })) 
{ 
    @Html.AntiForgeryToken() 
    <div class="modal-header"> 
     <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button> 
     <h4>Customer Search</h4> 
    </div> 
    <div class="modal-body"> 
     @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 
     <div class="form-group-sm clearfix"> 
      @Html.LabelFor(m => m.SearchVm.SearchCustomerNameNumber, new { @class = "control-label col-xs-5 col-md-5" }) 
      <div class="col-xs-5 col-md-5"> 
       <div class="input-group"> 
        @Html.EditorFor(m => m.SearchVm.SearchCustomerNameNumber, new {htmlAttributes = new {@class = "form-control"}}) 
        <span class="input-group-btn"> 
         <button type="submit" class="btn btn-custom-success btn-sm btn-custom-sm small-box-shadow btn-block"> 
          Search 
          <i class="fa fa-search fa-lg" aria-hidden="true"></i> 
         </button> 
        </span> 
       </div> 
       @Html.ValidationMessageFor(m => m.SearchVm.SearchCustomerNameNumber, "", new { @class = "text-danger" }) 
      </div> 
     </div> 
     <div class="modal-search" id="targetElement"> 
      @Html.Partial("_PermitsCustomerList", Model.SearchVm.Customers) 
     </div> 
    </div> 
} 

_PermitsCustomerList局部視圖,我有以下幾點:

@using PagedList 
@using PagedList.Mvc 
@model IPagedList<MyProject.ViewModels.CustomerViewModel> 
@if (Model != null && Model.Count > 0) 
{ 
    <div class="panel panel-default data-grid data-grid-wide"> 
     <table class="table table-hover table-striped table-bordered table-responsive"> 
      <tr> 
       <th> 
        Customer # 
       </th> 
       <th> 
        Customer Name 
       </th> 
      </tr> 
      @foreach (var item in Model) 
      { 
       <tr> 
        <td> 
         @Html.DisplayFor(modelItem => item.Customer_NO) 
        </td> 
        <td> 
         @Html.DisplayFor(modelItem => item.Customer_Name) 
        </td> 
       </tr> 
      } 
     </table> 
     <div id="contentPager"> 
      @Html.PagedListPager(Model, page => Url.Action("SearchCustomers", "Permits", 
       new { page }), 
       PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(new AjaxOptions() 
     { 
      HttpMethod = "POST", 
      UpdateTargetId = "targetElement", 
      OnSuccess = "onAjaxSuccess", 
      OnFailure = "onAjaxFailure" 
     })) 
     </div> 
    </div> 
} 

而這裏的控制器上的操作:

[HttpPost] 
[ValidateAntiForgeryToken] 
public PartialViewResult SearchCustomers(PermitsViewModel permitsVm, int? page) 
{ 
    if (string.IsNullOrEmpty(permitsVm.SearchVm.SearchCustomerNameNumber)) return null; 
    permitsVm.Page = page; 
    int number; 
    var list = int.TryParse(permitsVm.SearchVm.SearchCustomerNameNumber, out number) 
     ? CustomerDataService.SearchCustomerByNumber(number) 
     : CustomerDataService.SearchCustomerByName(permitsVm.SearchVm.SearchCustomerNameNumber); 

    return PartialView("_PermitsCreateCustomerList", list.ToPagedList(permitsVm.Page ?? 1, 10)); 
} 

這裏有成功和失敗的回調函數:

function onAjaxFailure(xhr, status, error) { 
    $("#targetElement").html("<strong>An error occurred retrieving data:" + error + "<br/>.</strong>"); 
} 
function onAjaxSuccess(data, status, xhr) { 
    if (!$.trim(data)) { 
     $("#targetElement").html("<div class='text-center'><strong>No results found for search.</strong></div>"); 
    } 
} 

我看了下這個例子:MVC 4 Using Paged List in a partial View並增加了PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing但仍有一些東西丟失。

當我使用Chrome瀏覽控制檯面板,它有這個錯誤,當我點擊頁碼:

http://localhost:9999/MyProject/Permits/SearchCustomers?page=2 500(內部服務器錯誤)

我在做什麼錯了,當試圖與PagedList組件進行AJAX調用?

回答

4

經過大量的試驗和錯誤的,答案是不使用視圖模型場進行搜索。

這裏的主視圖中的新搜索字段:

@{ 
    string searchName = ViewBag.SearchName; 
} 
@Html.EditorFor(x => searchName, new {htmlAttributes = new {@class = "form-control"}}) 

然後在操作,這一變化收到searchName值:

[HttpPost] 
[ValidateAntiForgeryToken] 
public PartialViewResult CreateSearch(string searchName, int? page) 
{ 
    if (string.IsNullOrEmpty(searchName)) return null; 
    int number; 
    var list = int.TryParse(searchName, out number) 
     ? CustomerDataService.SearchCustomerByNumber(number) 
     : CustomerDataService.SearchCustomerByName(searchName); 
    var permitsVm = new PermitsViewModel 
     {SearchVm = {Customers = list.ToPagedList(page ?? 1, 20)}}; 
    ViewBag.SearchName = searchName; 
    return PartialView("_PermitsCreateCustomerList", permitsVm); 
} 

ViewBag.SearchName;將用於將搜索字段值傳遞給部分視圖。

<div id="contentPager"> 
    @Html.PagedListPager(Model, page => Url.Action("SearchCustomers", "Permits", 
     new { ViewBag.SearchName, page }), 
     PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(new AjaxOptions() 
{ 
    HttpMethod = "POST", 
    UpdateTargetId = "targetElement", 
    OnSuccess = "onAjaxSuccess", 
    OnFailure = "onAjaxFailure" 
})) 
</div> 

在上述尋呼機制,我們使用ViewBag傳遞搜索值回到控制器。

更新1:您還需要在主視圖下,當你在頁面點擊數,以確保防僞標記(包含部分的一個)被髮送:

$.ajaxPrefilter(function(options, originalOptions, jqXHR) { 
    if (options.type.toUpperCase() === "POST") { 
     // We need to add the verificationToken to all POSTs 
     var token = $("input[name^=__RequestVerificationToken]").first(); 
     if (!token.length) return; 

     var tokenName = token.attr("name"); 

     // If the data is JSON, then we need to put the token in the QueryString: 
     if (options.contentType.indexOf('application/json') === 0) { 
      // Add the token to the URL, because we can't add it to the JSON data: 
      options.url += ((options.url.indexOf("?") === -1) ? "?" : "&") + token.serialize(); 
     } else if (typeof options.data === 'string' && options.data.indexOf(tokenName) === -1) { 
      // Append to the data string: 
      options.data += (options.data ? "&" : "") + token.serialize(); 
     } 
    } 
}); 

從這裏:https://gist.github.com/scottrippey/3428114

更新2:您可以使用控制器上的視圖模型,但必須通過RouteValueDictionary

<div id="contentPager"> 
    @Html.PagedListPager(Model, page => Url.Action("SearchCustomers", "Permits", 
     new RouteValueDictionary() 
    { 
     { "Page", page}, 
     { "SearchVm.SearchCustomerNameNumber", Model.SearchVm.SearchCustomerNameNumber } 
    }), 
     PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(new AjaxOptions() 
    { 
     HttpMethod = "POST", 
     UpdateTargetId = "targetElement", 
     OnSuccess = "onAjaxSuccess", 
     OnFailure = "onAjaxFailure" 
    })) 
</div> 

有了這個,你會改變的操作:

[HttpPost] 
[ValidateAntiForgeryToken] 
public PartialViewResult CreateSearch(PermitsViewModel permitsVm) 
{ 
    if (string.IsNullOrEmpty(permitsVm.SearchVm.SearchCustomerNameNumber)) return null; 
    int number; 
    var list = int.TryParse(permitsVm.SearchVm.SearchCustomerNameNumber, out number) 
     ? CustomerDataService.SearchCustomerByNumber(number) 
     : CustomerDataService.SearchCustomerByName(permitsVm.SearchVm.SearchCustomerNameNumber); 
    permitsVm.SearchVm.Customers = list.ToPagedList(permitsVm.Page ?? 1, 10); 
    return PartialView("_PermitsCreateCustomerList", permitsVm); 
} 

的複雜對象的RouteValueDictionary幫助從這裏走過:https://stackoverflow.com/a/23743358/177416

1

它看起來像你沒有傳遞一個必要的參數到你的控制器。您PagedListPager改成這樣:(!主要是錯誤)

@Html.PagedListPager(Model, page => Url.Action("SearchCustomers", "Permits", new { page = page, permitsVm = Json.Encode(Model)}), PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(new AjaxOptions() { HttpMethod = "POST", UpdateTargetId = "targetElement", OnSuccess = "onAjaxSuccess", OnFailure = "onAjaxFailure" }))