Skip to content

Instantly share code, notes, and snippets.

@hidegh
Created April 4, 2018 19:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hidegh/d503b411e30e57d6b5276e5d67dad44a to your computer and use it in GitHub Desktop.
Save hidegh/d503b411e30e57d6b5276e5d67dad44a to your computer and use it in GitHub Desktop.
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