Search code examples
c#asp.net-web-apiodata

How to add absent OData Query Option inside the controller action


I've Product Entity in my OData EDM, with a GUID key property, but I want to enforce results of the EntitySet to be sorted with another property Number if $orderby is not used. So I want to be able to use $orderby normally, but in case it is absent, I want to add it inside the controller action to ODataQueryOptions, here is what I reached to so far.

[EnableQuery()]
public IQueryable<Product> Get(ODataQueryOptions<Product> queryOptions)
{
    if (queryOptions.OrderBy == null)
    {
        // do something to add $orderby=Number to queryOptions
    }

    return _ProductRepository.GetAll();
}

The problem here is that queryOptions.OrderBy is read-only and I cannot assign to it.

Any Suggestions? Please.


Solution

  • I ended up implementing an Attribute that inherits from EnableQueryAttribute as proposed in this answer https://stackoverflow.com/a/41933056/236384 by @afshar-mohebbi

    The action code now looks like this:

    [CustomizedEnableQuery()]
    public IQueryable<Product> Get()
    {
        return _ProductRepository.GetAll();
    }
    

    The attribute implementation looks like this:

    public class CustomizedEnableQueryAttribute : EnableQueryAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            var url = actionContext.Request.RequestUri.OriginalString;
    
            // add $orderby=Number to url
            if (url.ToLower().IndexOf("$orderby") == -1)
            {
                var orderByClause = "$orderby=Number";
                var newUrl = url.IndexOf('?') == -1
                    ? $"{url}?{orderByClause}"
                    : $"{url}&{orderByClause}";
    
                actionContext.Request.RequestUri = new Uri(newUrl);
            }
    
            base.OnActionExecuting(actionContext);
        }
    }
    

    Hope this helps somebody later,