ASP.NET Web Api 實現數據的分頁


前言

這篇文章我們將使用不同的方式實現手動分頁(關於高端大氣上檔次的OData本文暫不涉及,但有可能會在系列的后期介紹,還沒確定。。。),對於分頁的結果,我們將采用2種不同的方式響應給客戶端(1.將分頁元數據封裝在響應Body中2.在http響應報文頭部添加分頁信息)。

眾所周知,在服務器端一次性返回成百上千條數據是非常恐怖的,在我們設計Api的時候,對於Get方法我們應該以分頁的方式返回。例如:每次響應給客戶端10條數據,並且包含“上一頁”和“下一頁”的標簽,這樣用戶就能去獲得他想要的數據。

Way1.封裝分頁元數據封裝在響應Body中

修改“CoursesController”的Get方法實現分頁而不是一次性把所有數據返回,下面上代碼:

復制代碼
復制代碼
public Object Get(int page = 0, int pageSize = 10)
     {
         IQueryable<Course> query;
 
         query = TheRepository.GetAllCourses().OrderBy(c => c.CourseSubject.Id);
         var totalCount = query.Count();
         var totalPages = (int)Math.Ceiling((double)totalCount / pageSize);
 
         var urlHelper = new UrlHelper(Request);
         var prevLink = page > 0 ? urlHelper.Link("Courses", new { page = page - 1 }) : "";
         var nextLink = page < totalPages - 1 ? urlHelper.Link("Courses", new { page = page + 1 }) : "";
 
         var results = query
                       .Skip(pageSize * page)
                       .Take(pageSize)
                       .ToList()
                       .Select(s => TheModelFactory.Create(s));
 
         return new
         {
             TotalCount = totalCount,
             TotalPages = totalPages,
             PrevPageLink = prevLink,
             NextPageLink = nextLink,
             Results = results
         };
 
     }
復制代碼
復制代碼

解釋一下上面的代碼:

    在Get方法上添加了2個有默認值的參數,這兩個參數就是用來過濾我們查詢結果集的——例如:我們想獲取第2頁的數據,那么對應的Get請求就應該是這種形式:http://localhost:{your_port}/api/courses/?page=1,注意:在這里我們只給了一個參數,那么pageSize就是默認值10.

客戶端收到的部分響應就應該是:

復制代碼
復制代碼
{
    "totalCount": 32,
    "totalPages": 4,
    "prevPageLink": "http://localhost:3300/api/courses?page=0&pageSize=10",
    "nextPageLink": "http://localhost:3300/api/courses?page=2&pageSize=10",
    "results": [
        {
            "id": 11,
            "url": "http://localhost:3300/api/courses/11",
            "name": "English Education 2",
            "duration": 4,
            "description": "The course will talk in depth about: English Education 2",
            "tutor": {
                "id": 4,
                "email": "Kareem.Ismail@outlook.com",
                "userName": "KareemIsmail",
                "firstName": "Kareem",
                "lastName": "Ismail",
                "gender": 0
            },
            "subject": {
                "id": 4,
                "name": "English"
            }
        },
復制代碼
復制代碼

  Repository中GetAllCourses的返回值為IQueryable,因此在執行skip和take方法時並沒有到SQL Server中執行SQL語句,最后查詢的也是分頁好的數據,體現出按需查詢的特色。

 

在我們返回給客戶端的數據中,其中分頁元數據中包含了totalCount, totalPages, prevPageLink, nextPageLink這些數據,對於客戶端來說我們返回totalCount, totalPages這兩條數據非常有用,這樣就可以與一些Grid配合使用來綁定結果。

 

通常來說我們會將分頁元數據封裝在響應Body中,對於開發者來說我們提供了所有分頁信息。但有的API消費者因此只想獲取它請求的數據而不需要分頁元數據,那么他在解析響應結果是就會很費勁,因此這里出現了另一種方式來向客戶端響應分頁元數據——在響應報文頭部附加分頁元數據:Body部分只包含請求的資源,我們新增一個頭部信息“X-Pagination”。

Way2.封裝分頁元數據到響應Header中

我們修改StudentsController來實現將分頁元數據封裝在Header中,使用這種方法后,需要分頁元數據的客戶端直接從Header部分獲取,不需要的客戶端直接解析響應的Body即可。

實現起來也非常簡單,下面上代碼:

復制代碼
復制代碼
public IEnumerable<StudentBaseModel> Get(int page = 0, int pageSize = 10)
        {
            IQueryable<Student> query;

            query = TheRepository.GetAllStudentsWithEnrollments().OrderBy(c => c.LastName);

            var totalCount = query.Count();
            var totalPages = (int)Math.Ceiling((double)totalCount / pageSize);

            var urlHelper = new UrlHelper(Request);
            var prevLink = page > 0 ? urlHelper.Link("Students", new { page = page - 1, pageSize = pageSize }) : "";
            var nextLink = page < totalPages - 1 ? urlHelper.Link("Students", new { page = page + 1, pageSize = pageSize }) : "";

            var paginationHeader = new
            {
                TotalCount = totalCount,
                TotalPages = totalPages,
                PrevPageLink = prevLink,
                NextPageLink = nextLink
            };

            System.Web.HttpContext.Current.Response.Headers.Add("X-Pagination",
                                                                Newtonsoft.Json.JsonConvert.SerializeObject(paginationHeader));

            var results = query
                        .Skip(pageSize * page)
                        .Take(pageSize)
                        .ToList()
                        .Select(s => TheModelFactory.CreateSummary(s));

            return results;
        }
復制代碼
復制代碼

這里我們添加了一個Header,里面包含一個Json序列化的分頁元數據,客戶端收到的響應:

QQ截圖20140209221847

總結

2種分頁技術各有優劣,感覺碰到具體應用的時候再做選擇了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM