Search code examples
asp.net-web-api2odataodata-v4

How to control presence of OData error details


I'm trying to control the presence of details in error responses from a Web API 2 OData v4 service. When I hit the OData service hosted on my local IIS, I get something like this:

{
  "error": {
    "code": "Error code",
    "message": "Message from exception filter",
    "details": [
      {
        "code": "Detail code",
        "message": "Details here"
      }
    ],
    "innererror": {
      "message": "Exception message here",
      "type": "Exception type",
      "stacktrace": "Stack trace here"
    }
  }
}

When I take the same service and deploy it on a remote server, and hit it with the same message, I get this:

{
  "error": {
    "code": "Error code",
    "message": "Message from exception filter"
  }
}

I'm guessing that the "innererror" and "details" sections are suppressed because I'm calling the service remotely? I'm happy that the "innererror" section is suppressed - I don't want to leak those details - but I want to expose the "details" section so that I can provide some more feedback on certain errors. Is there a simple way to achieve this?

Thanks!


Solution

  • I was creating my OData error responses using Request.CreateErrorResponse(myHttpStatusCode, myODataError). Looking at the source code of System.Web.Http.OData.Extensions.HttpRequestMessageExtensions.CreateErrorResponse, it appears that if Request.ShouldIncludeErrorDetail is false, then the ODataError is recreated with just the "code" and "message" items. My solution was to create another overload/extension of CreateErrorResponse which accepts a parameter that controls whether the details section should be included:

    public static HttpResponseMessage CreateErrorResponse(this HttpRequestMessage request,
                HttpStatusCode statusCode, ODataError oDataError, bool includeDetails)
    {
        if (request.ShouldIncludeErrorDetail())
        {
            return request.CreateResponse(statusCode, oDataError);
        }
        else
        {
            return request.CreateResponse(
                statusCode,
                new ODataError()
                {
                    ErrorCode = oDataError.ErrorCode,
                    Message = oDataError.Message,
                    Details = includeDetails ? oDataError.Details : null
                });
        }
    }
    

    This allows the "innererror" section to be suppressed independently of the "details" section.