Webapi: aspnet core Queries still try to run on error results.

Created on 16 May 2019  路  2Comments  路  Source: OData/WebApi


If a route throws an error, and the user tries to query it, you will lose the error and get an error about how the query is invalid.

Assemblies affected

using:
"Microsoft.AspNetCore.OData" Version="7.1.0"
"Microsoft.OData.Core" Version="7.5.4"
"Microsoft.AspnetCore.App" Version=2.24"

Reproduce steps

Create a controller like so:

public class Always400Controller : ODataController
{
      [EnableQuery]
      public IHttpActionResult Get()
      {
             return BadRequest(new ODataError{Message="This route gives a 400"});
      }
}

Now hit it with your web browser
/Always400?$top=1

Expected result

You should get a 400 error with the following output

{"error":{"code":"","message":"This route gives a 400"}}

Actual result

You get a 500 error with the following output

{"error":{"code":"","message":"The query specified in the URI is not valid. The requested resource is not a collection. Query options $filter, $orderby, $count, $skip, and $top can be applied only on collections.","details":[],"innererror":{"message":"The requested resource is not a collection. Query options $filter, $orderby, $count, $skip, and $top can be applied only on collections.","type":"Microsoft.OData.ODataException","stacktrace":" at Microsoft.AspNet.OData.EnableQueryAttribute.ValidateSelectExpandOnly(ODataQueryOptions queryOptions)rn at Microsoft.AspNet.OData.EnableQueryAttribute.ExecuteQuery(Object responseValue, IQueryable singleResultCollection, IWebApiActionDescriptor actionDescriptor, Func2 modelFunction, IWebApiRequestMessage request, Func2 createQueryOptionFunction)rn at Microsoft.AspNet.OData.EnableQueryAttribute.OnActionExecuted(Object responseValue, IQueryable singleResultCollection, IWebApiActionDescriptor actionDescriptor, IWebApiRequestMessage request, Func2 modelFunction, Func2 createQueryOptionFunction, Action1 createResponseAction, Action3 createErrorAction)"}}}

bug

Most helpful comment

Investigating the error seems to be here
https://github.com/OData/WebApi/blob/3b1ecc572088ff1c1abc5147b29191cfe3afbe58/src/Microsoft.AspNetCore.OData/EnableQueryAttribute.cs#L75-L76

Basically, BadRequestObjectResult and other ObjectResult errors do not inherit from StatusCodeResult.
The solution would be to use IStatusCodeActionResult like so::

 var statusCodeResult = actionExecutedContext.Result as IStatusCodeActionResult;
 if (statusCodeResult is null || !statusCodeResult.StatusCode.HasValue 
|| IsSuccessStatusCode(statusCodeResult.StatusCode.Value))

After staring at the code, I found this workaround, but I hate it.

if(errorCondition)
{
        HttpContext.Response.Status = 400;
        return new BadRequestObjectResult(...);
}

All 2 comments

Investigating the error seems to be here
https://github.com/OData/WebApi/blob/3b1ecc572088ff1c1abc5147b29191cfe3afbe58/src/Microsoft.AspNetCore.OData/EnableQueryAttribute.cs#L75-L76

Basically, BadRequestObjectResult and other ObjectResult errors do not inherit from StatusCodeResult.
The solution would be to use IStatusCodeActionResult like so::

 var statusCodeResult = actionExecutedContext.Result as IStatusCodeActionResult;
 if (statusCodeResult is null || !statusCodeResult.StatusCode.HasValue 
|| IsSuccessStatusCode(statusCodeResult.StatusCode.Value))

After staring at the code, I found this workaround, but I hate it.

if(errorCondition)
{
        HttpContext.Response.Status = 400;
        return new BadRequestObjectResult(...);
}

This is also broken in 7.2 still. It's disappointing that very little was fixed.

Was this page helpful?
0 / 5 - 0 ratings