Created
February 4, 2017 22:46
-
-
Save nth-commit/94e390b089ca662df972acd06d1d4fce to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class OkPagedResult : OkObjectResult | |
{ | |
public int TotalItems { get; private set; } | |
public OkPagedResult(IEnumerable items, int totalItems) : base(items) | |
{ | |
TotalItems = totalItems; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public abstract class PagedController : Controller | |
{ | |
public OkPagedResult Ok(IEnumerable items, int totalItems) | |
{ | |
return new OkPagedResult(items, totalItems); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class PagingAttribute : Attribute, IActionFilter | |
{ | |
private const string DefaultPageNumberKey = "page"; | |
private const string DefaultPageSizeKey = "page-size"; | |
public void OnActionExecuting(ActionExecutingContext context) | |
{ | |
} | |
public void OnActionExecuted(ActionExecutedContext context) | |
{ | |
var okPagedResult = context.Result as OkPagedResult; | |
if (okPagedResult != null) | |
{ | |
AddTotalCountHeader(context, okPagedResult); | |
AddLinkHeader(context, okPagedResult); | |
} | |
} | |
private void AddTotalCountHeader(ActionExecutedContext context, OkPagedResult result) | |
{ | |
var totalItems = result.TotalItems; | |
context.HttpContext.Response.Headers.Add("X-Total-Count", new StringValues(totalItems.ToString())); | |
} | |
private void AddLinkHeader(ActionExecutedContext context, OkPagedResult result) | |
{ | |
var pageNumber = _pageRequest.Number; | |
var totalPages = (int)Math.Ceiling(result.TotalItems / (double)_pageRequest.Size); | |
var links = new List<LinkHeaderElement>() | |
{ | |
new LinkHeaderElement() | |
{ | |
Rel = "first", | |
Url = GetPageUrl(context, 1) | |
}, | |
new LinkHeaderElement() | |
{ | |
Rel = "last", | |
Url = GetPageUrl(context, totalPages) | |
} | |
}; | |
if (totalPages > 1) | |
{ | |
if (pageNumber < totalPages) | |
{ | |
links.Add(new LinkHeaderElement() | |
{ | |
Rel = "next", | |
Url = GetPageUrl(context, pageNumber + 1) | |
}); | |
} | |
if (pageNumber > 1) | |
{ | |
links.Add(new LinkHeaderElement() | |
{ | |
Rel = "prev", | |
Url = GetPageUrl(context, pageNumber - 1) | |
}); | |
} | |
} | |
var linksHeaderValues = links.Select(l => $"<{l.Url}>; rel=\"{l.Rel}\""); | |
context.HttpContext.Response.Headers.Add("Link", string.Join($", ", linksHeaderValues)); | |
} | |
private string GetPageUrl(ActionExecutedContext context, int pageNumber) | |
{ | |
var request = context.HttpContext.Request; | |
var requestQueryDictionary = QueryHelpers.ParseQuery(request.QueryString.Value); | |
requestQueryDictionary[DefaultPageNumberKey] = new StringValues(pageNumber.ToString()); | |
requestQueryDictionary[DefaultPageSizeKey] = new StringValues(_pageRequest.Size.ToString()); | |
return QueryHelpers.AddQueryString( | |
new Uri($"{request.Scheme}://{request.Host}{request.Path}").ToString(), | |
requestQueryDictionary | |
.Where(kvp => kvp.Value.Count() > 0) | |
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.FirstOrDefault())); | |
} | |
private class LinkHeaderElement | |
{ | |
public string Rel { get; set; } | |
public string Url { get; set; } | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment