Skip to content

Instantly share code, notes, and snippets.

@akunzai
Last active August 29, 2015 14:21
Show Gist options
  • Save akunzai/cd929815d7cda72ef78a to your computer and use it in GitHub Desktop.
Save akunzai/cd929815d7cda72ef78a to your computer and use it in GitHub Desktop.
OData PageLink Header Builder
using System.Collections.Generic;
using System.Web.Http;
using System.Web.Http.Routing;
namespace System.Net.Http {
/// <summary>
/// OData PageLink Header Builder
/// </summary>
//http://www.jerriepelser.com/blog/paging-in-aspnet-webapi-pagination-links
public class ODataPageLinkBuilder {
public const string TOTAL_COUNT_HEADER = "X-Total-Count";
public const string SKIP = "$skip";
public const string TOP = "$top";
private const string FIRST = "first";
private const string LAST = "last";
private const string PREV = "prev";
private const string NEXT = "next";
private const string LINK = "Link";
private const string LINK_TEMPLATE = "<{0}>; rel=\"{1}\"";
public Uri FirstPage { get; private set; }
public Uri LastPage { get; private set; }
public Uri NextPage { get; private set; }
public Uri PreviousPage { get; private set; }
public ODataPageLinkBuilder(UrlHelper urlHelper,
string routeName, object routeValues,
int skip, int top, long totalItemCount) {
// Determine total number of pages
var pageCount = totalItemCount > 0
? (int)Math.Ceiling(totalItemCount / (double)top)
: 0;
var pageNumber = skip > 0
? (int)Math.Ceiling(skip / (double)top) + 1
: 1;
// Create them page links
FirstPage = new Uri(
urlHelper.Link(
routeName,
new HttpRouteValueDictionary(routeValues) {
{ SKIP, 0 },
{ TOP, top }
}));
LastPage = new Uri(
urlHelper.Link(
routeName,
new HttpRouteValueDictionary(routeValues) {
{ SKIP, (pageCount - 1) * top },
{ TOP, top }
}));
if (pageNumber > 1) {
PreviousPage = new Uri(
urlHelper.Link(
routeName,
new HttpRouteValueDictionary(routeValues) {
{ SKIP, skip - top > 0 ? skip - top : 0 },
{ TOP, top }
}));
}
if (pageNumber < pageCount) {
NextPage = new Uri(
urlHelper.Link(
routeName,
new HttpRouteValueDictionary(routeValues) {
{ SKIP, skip + top },
{ TOP, top }
}));
}
}
public string GetLink(Uri pageUri, string relName) {
return string.Format(LINK_TEMPLATE, pageUri, relName);
}
public string GetLinks() {
var links = new List<string>();
if (FirstPage != null) {
links.Add(GetLink(FirstPage, FIRST));
}
if (PreviousPage != null) {
links.Add(GetLink(PreviousPage, PREV));
}
if (NextPage != null) {
links.Add(GetLink(NextPage, NEXT));
}
if (LastPage != null) {
links.Add(GetLink(LastPage, LAST));
}
return string.Join(", ", links);
}
public static HttpResponseMessage Build(ApiController control,
string routeName,
HttpResponseMessage response,
int skip,int top,int totalItemCount) {
response.Headers.TryAddWithoutValidation(TOTAL_COUNT_HEADER, totalItemCount.ToString());
if (top > 0) {
var linkBuilder = new ODataPageLinkBuilder(control.Url, routeName, control.Request.GetRouteData().Values, skip, top, totalItemCount);
response.Headers.Add(LINK, linkBuilder.GetLinks());
}
return response;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment