Created
April 4, 2018 19:14
-
-
Save hidegh/d503b411e30e57d6b5276e5d67dad44a to your computer and use it in GitHub Desktop.
This file contains hidden or 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
using Microsoft.AspNetCore.Mvc; | |
using Microsoft.AspNetCore.Mvc.Filters; | |
using Microsoft.AspNet.OData; | |
using Microsoft.AspNet.OData.Extensions; | |
using Microsoft.AspNet.OData.Query; | |
using System.Linq; | |
using System; | |
using Newtonsoft.Json; | |
namespace R.Web.Api | |
{ | |
/// <summary> | |
/// Replacement for Microsoft.AspNet.OData.EnableQueryAttribute that returns a valid OData response, see: ODataPagedResult. | |
/// </summary> | |
public class ODataQueryable : EnableQueryAttribute | |
{ | |
public override IQueryable ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions) | |
{ | |
// NOTE: altering OData query: | |
// https://d-fens.ch/2017/02/26/modifying-odataqueryoptions-on-the-fly/ | |
// https://tutel.me/c/programming/questions/33660648/odata+v4+modify+filter+on+server+side | |
var baseResult = base.ApplyQuery(queryable, queryOptions); | |
return baseResult; | |
} | |
public override void OnActionExecuted(ActionExecutedContext actionExecutedContext) | |
{ | |
// NOTE: | |
// issue https://github.com/OData/WebApi/issues/159 | |
// workaround: https://stackoverflow.com/questions/27545207/items-count-in-odata-v4-webapi-response | |
base.OnActionExecuted(actionExecutedContext); | |
// Skip post processing on exceptions... | |
if (actionExecutedContext.Exception != null) | |
return; | |
// ...and on errors | |
var response = actionExecutedContext.HttpContext.Response; | |
if (response == null || !response.IsSuccessStatusCode() || actionExecutedContext.Result == null) | |
return; | |
// | |
// Post-process | |
var responseContent = actionExecutedContext.Result as ObjectResult; | |
var items = responseContent?.Value as IQueryable; | |
if (items == null) | |
throw new NotSupportedException($"Controller action result with OData queries applied has to be an IQueryable<>, returned type is: {responseContent?.Value?.GetType()}!"); | |
// NOTE: if below does not work, we can try: count = long.Parse(Request.Properties["System.Web.OData.TotalCount"].ToString()) | |
var nextLink = actionExecutedContext.HttpContext.Request.ODataFeature().NextLink; | |
var count = actionExecutedContext.HttpContext.Request.ODataFeature().TotalCount; | |
responseContent.Value = new ODataPagedResult(items, nextLink, count); | |
} | |
} | |
/// <summary> | |
/// NOTE: theres a PageResult<T> class already in .NET but it does not serialize via JSON as proper OData result... | |
/// </summary> | |
public class ODataPagedResult | |
{ | |
public ODataPagedResult(IQueryable items, Uri nextLink, long? count) | |
{ | |
Value = items; | |
NextLink = nextLink?.ToString() ?? ""; | |
Count = count; | |
} | |
[JsonProperty("value")] | |
public IQueryable Value { get; set; } | |
[JsonProperty("@odata.count")] | |
public long? Count { get; set; } | |
[JsonProperty("@odata.nextLink")] | |
public string NextLink { get; set; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment