2017-03-06 56 views
5

Visual Studio 2015を使用してASP.NET MVC 5アプリケーションを構築しています。最初の試行では正常に動作しますが、 MVC PagedList componentInternal Server Errorがスローされます。ここにAJAXフォームがあります。それは部分的に表示する検索から受信したデータを渡すことに注意してください:ASP.NET MVC PagedList(部分ビューでAJAXを使用)

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

そして、ここでのコントローラーのアクション:_PermitsCustomerList部分図で

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

、私は以下の持っている

ここで
[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 ViewPagedListRenderOptions.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を渡すことができます:

012これにより

、アクション変更したい:

[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" }))

関連する問題