ASP.NET MVC 4 實作PagedList.Mvc + AJAX 搜尋功能

  • 4809
  • 0
  • MVC
  • 2017-09-27

剛步入ASP.NET MVC架構的空間,前一份工作只是修修改改PHP和部分的.NET。所以整個還很菜阿,目的記錄自己學習的過程,以及希望有任何一位前輩覺得哪寫錯或方法很爛,麻煩順便可以大發慈悲的指點一下。

那麼準備開始從大多數專案都會碰到的CRUD來寫起吧,雖然很多API可以去串接很快速達到所要的功能,但練功還是自己慢慢地刻出一個畫面再說。

首先,此篇是參考 KEVIN 前輩的文章,再加入自己的應用和想法產生出來的,正所謂凡事先從模仿開始,但千萬別一開始就去學灌籃吧。相對這篇也不適合第一次接觸MVC沒有開發經驗的人閱讀。

 

本文引用kevin前輩文章,謝謝分享那麼優的文章。

ASP.NET MVC 資料分頁操作 - 使用 PagedList.Mvc @ GitHub

當參考Kevin前輩的 「ASP.NET MVC 資料分頁操作 - 使用 PagedList.Mvc @ GitHub」系列文章發現Ajax那篇文章有實際做到,但分頁進階處理此篇文章就每一次都會重新整理頁面。

於是本篇文章就,利用這兩篇文章做一個簡單的結合,達到搜尋的結果也可以呈現AJAX。

首先實際做完Kevin前輩的文章Part 3 Ajax部分會得到類似下圖的Table,當然沒有上面搜尋的功能。

 

 

 

 

 

 

 

 

 

首先把顯示頁面的搜尋欄位建好,程式碼如下

<div class="container">
    
        <div class="row">
            <div class="col-md-10 col-md-offset-1">
                <div class="well">
                    <div class="col-xs-6 form-group">
                        <label class="col-xs-3 control-label">CustomerID:</label>
                        <div class="col-xs-8">
                            @Html.TextBox("CustomerID", "", new { htmlAttributes = new { @class = "form-control", @id = "CustomerID" } })
                        </div>
                    </div>
                    <div class="col-md-6 form-group">
                        <label class="col-xs-3 control-label">CompanyName:</label>
                        <div class="col-xs-8">
                            @Html.TextBox("CompanyName", "", new { htmlAttributes = new { @class = "form-control", @id = "CompanyName" } })
                        </div>
                    </div>

                    <span class="clearfix"></span>
                    <div class="row">
                        <div class="col-md-offset-5">
                            <input id="Serach" type="button" class="btn btn-primary" value="Search">
                            <span></span>
                            <input id="re" type="button" class="btn btn-default" value="Cancel">
                        </div>
                    </div>
                </div>
            </div>
        </div>
 
</div>

接下來是搜尋的Controller部分,但實作搜尋篩選資料並不是放在Controller內。搜尋的方式我會用POST的方式來傳遞參數

[HttpPost]
public ActionResult PagedPartial(string CustomerID = null, string CompanyName = null, int page = 1)
{

   var query = this.custromService.Search(CustomerID, CompanyName);

   int currentPage = page < 1 ? 1 : page;

   var result = query.ToPagedList(currentPage, pageSize);

   ViewData.Model = result;

   return PartialView("_DataTable");
}

實作的搜尋方法我放在Service裡來實作這個功能,跟我一樣還很菜的不懂這一段怎麼來的朋友依然可以參考Kevin前輩的文章「ASP.NET MVC 專案分層架構 Part.1 初學者的起手式」這系列的文章。

public IEnumerable<Customers> Search(string CustomerID, string CompanyName)
{
   var query = this.repostitory.GetAll().AsQueryable();

   if (!string.IsNullOrWhiteSpace(CustomerID))
   {
      query = query.Where(x => x.CustomerID.Contains(CustomerID));
   }

   if (!string.IsNullOrWhiteSpace(CompanyName))
   {
      query = query.Where(x => x.CompanyName.Contains(CompanyName));
   }

   query = query.OrderByDescending(x => x.CustomerID);

   return query;
}

當後端的方式都完整的建立好的時候,再來就剩下前端的部分,在前端採用jQuery來傳送參數給Controller。在View的部分會有兩個檔案,一個作為部分加入的頁面,一個是我們連到網站會看到的頁面。

View
    __DataTable.cshtml <--- PartialView
    Index.cshtml <--主要顯示畫面

先來看_DataTable.cshtml的內容。此為TABLE所顯示的資料畫面,這個沒什麼好講的,看完Kevin前輩的文章都可以很容易的理解。

@using PagedList
@using PagedList.Mvc
@model IPagedList<Ajax_CRUD_Model.Customers>

<div class="container-full">
    <div class="row">
        <div class="col-md-10 col-md-offset-1">
            <div class="panel panel-default panel-table">
                <div class="panel-heading">
                    <div class="row">
                        <div class="col col-xs-6">
                            <h3 class="panel-title">Customer</h3>
                        </div>
                        <div class="col col-xs-6 text-right">
                            <button data-toggle="modal" data-target="#squarespaceModal" class="btn btn-sm btn-primary btn-create">Create New</button>
                        </div>
                    </div>
                </div>
                <div class="panel-body">
                    <table class="table table-striped table-bordered table-list">
                        <thead>
                            <tr>
                                <th><em class="fa fa-cog"></em></th>

                                <th>@Html.DisplayNameFor(model => model.FirstOrDefault().CustomerID)</th>
                                <th>@Html.DisplayNameFor(model => model.FirstOrDefault().CompanyName)</th>
                                <th>@Html.DisplayNameFor(model => model.FirstOrDefault().ContactName)</th>
                                <th>@Html.DisplayNameFor(model => model.FirstOrDefault().ContactTitle)</th>
                                <th>@Html.DisplayNameFor(model => model.FirstOrDefault().Country)</th>
                                <th>@Html.DisplayNameFor(model => model.FirstOrDefault().City)</th>
                                <th>@Html.DisplayNameFor(model => model.FirstOrDefault().PostalCode)</th>
                                <th>@Html.DisplayNameFor(model => model.FirstOrDefault().Phone)</th>
                                <th>@Html.DisplayNameFor(model => model.FirstOrDefault().Fax)</th>
                                <th>@Html.DisplayNameFor(model => model.FirstOrDefault().Address)</th>
                                <th>@Html.DisplayNameFor(model => model.FirstOrDefault().Region)</th>
                              
                            </tr>
                        </thead>
                        <tbody>
                            @foreach (var item in Model)
                            { 
                                <tr>
                                    <td align="center">
                                        <button id="TETT" onclick="getValue('@item.CustomerID','@item.CompanyName')"  data-toggle="modal" data-target="#Ediotr" class="btn btn-sm btn-default fa fa-pencil"></button>
                                        <button data-toggle="modal" onclick="GetDeletValue('@item.CustomerID','@item.CompanyName')"  data-target="#Delete" class="btn btn-sm btn-danger fa fa-trash"></button>
                                    </td>

                                    <td>@Html.DisplayFor(modelItem => item.CustomerID)</td>
                                    <td>@Html.DisplayFor(modelItem => item.CompanyName)</td>
                                    <td>@Html.DisplayFor(modelItem => item.ContactName)</td>
                                    <td>@Html.DisplayFor(modelItem => item.ContactTitle)</td>
                                    <td>@Html.DisplayFor(modelItem => item.Country)</td>
                                    <td>@Html.DisplayFor(modelItem => item.City)</td>
                                    <td>@Html.DisplayFor(modelItem => item.PostalCode)</td>
                                    <td>@Html.DisplayFor(modelItem => item.Phone)</td>
                                    <td>@Html.DisplayFor(modelItem => item.Fax)</td>
                                    <td>@Html.DisplayFor(modelItem => item.Address)</td>
                                    <td>@Html.DisplayFor(modelItem => item.Region)</td>

                                </tr>
                                
                            }
                        </tbody>
                    </table>
                </div>
                <div class="panel-footer">


                    @Html.PagedListPager(Model, page => Url.Action("Index", new { page }))

                </div>
            </div>
        </div>
    </div>
</div>





重點在Index上面,有事前先做好的搜尋,在搜尋的下面再加上一個DIV作為部分參照的資料載入的地方。(此部分Kevin前輩內文都有詳細的說明)

<!--DataTable Ajax 插入位置-->
<div id="CustomerData"></div>

Kevin的原文內容在搜尋分頁那篇,是採用

@using (Html.BeginForm)

這個方式來對Controller來傳遞參數,這樣網頁Return一定會因此refresh。

所以在此改用Kevin系列文章的「ASP.NET MVC 資料分頁 - 使用 PagedList.Mvc:AJAX」此篇方法來做修改,達到Ajax的部分。

<!--Ajax 查詢以及顯示清單-->
<script>
    $(function () {
        var page = window.location.hash
            ? window.location.hash.slice(1)
            : 1;
        fetchPage(page);

        $('#Serach').click(function () {
            fetchPage(page);
        });


        $('#re').click(function () {
            $('#CustomerID').val("");
            $('#CompanyName').val("");
            fetchPage(page);
        });
    });

    var List = function () {

        $('#BankData .pagination li a').each(function (i, item) {
            var hyperLinkUrl = $(item).attr('href');
            if (typeof hyperLinkUrl !== 'undefined' && hyperLinkUrl !== false) {
                var pageNumber = $(item).attr('href').replace('/Customer?page=', '');
                $(item).attr('href', '#').click(function (event) {
                    event.preventDefault();
                    $(event.target).attr('href');
                    fetchPage(pageNumber);
                });
            }
        });
    };

    var fetchPage = function (page) {

        var pagedPartialUrl = '@Url.Action("PagedPartial", "Customer")';
        var CustomerID = $('#CustomerID').val();
        var CompanyName = $('#CompanyName').val();

        if (CustomerID != null || CustomerID != "" || CompanyName != null || CompanyName != "") {
            pagedPartialUrl = '@Url.Action("PagedPartial", "Customer")';
            $.post(pagedPartialUrl, { page: page, CustomerID: CustomerID, CompanyName: CompanyName }, function (data) {
                window.location.hash = page;
                $('#BankData').html(data);
                List();
            });
        } else {
            $.post(pagedPartialUrl, { page: page }, function (data) {

                window.location.hash = page;

                $('#BankData').html(data);

                List();
            });
        }
    };

</script>

fetchPage() => 傳遞參數以及抓取Ajax Data,所以對Controller也是這裡溝通。

List () => 抓取分頁,因為這裡所以才可進行AJAX的分頁,以及搜尋的分頁,這是完全依照Kevin前輩的文章,由於小弟很菜,jQuery功力更慘只好先依照前輩的文章來使用,詳細自行參考吧,不太了解這部分的意思。但這是功能的重點。代表我還不夠認真只好再努力多念點書了....

本篇的修改的點在於fetchPage的修改,改成一部分有傳遞搜尋參數,另一個只有傳遞page,再加入兩個Button來作為搜尋功能的依據,再將Kevin前輩的List()部份抽離出來獨立成為一個函數,避免掉要重複寫一段一樣的塞在fetchPage內。

簡單的修改一些部分就能達到Ajax 的資料頁面拉。

下一篇會來介紹One Page 達到 CRUD的應用,記得兩個多月前第一個MVC專案的開始,一個功能一個PAGE多煩阿,兩個月後,開始懂得應用jQuery去對Controller呼叫Action來做使用,解決掉我很多的新手問題,後續會再將這些相關的練習發給大家參考,希望我是有慢慢再進步的,菜鳥文,下台一鞠躬。