user2883779
user2883779

Reputation: 191

Error Handling for ASP.NET Odata Web API

I'm interested in knowing what are the best practices being followed to raise exceptions in the ODataController.

If you raise an exception in the method it is translated to response code of 500 by default and the content has details on the error. I would like to be explicit of the response code and send 400 in cases of invalid key.

For example: If the input request has an invalid key would like to return a HttpResponseCode of 400 and content should have the error details similar to raising an exception.

Thanks a lot for your inputs

Upvotes: 19

Views: 20425

Answers (4)

flipdoubt
flipdoubt

Reputation: 14435

For ASP.NET Core with OData, replace the EnableQueryAttribute on your Get method with a custom attribute that catches ODataException and throws a custom exception. In most cases, this allows standard error handling to step in as expected. Originally found this solution at https://github.com/OData/WebApi/issues/1898.

For your custom attribute, use something like the following:

public class CustomEnableQueryAttribute : EnableQueryAttribute
{
    public override void ValidateQuery(HttpRequest request, ODataQueryOptions queryOptions)
    {
        try
        {
            base.ValidateQuery(request, queryOptions);
        }
        catch (ODataException e)
        {
            throw new CustomException(e.Message, e){UserMessage = "Invalid OData query."};
        }
    }
}

On your Get method, use something like the following:

[HttpGet, CustomEnableQuery]
public virtual IQueryable<TDomainDto> Get()
{
    return Repository.Get();    
}

Upvotes: 3

Shenron
Shenron

Reputation: 47

Check CreateErrorResponse in the OData documentation. The namespace to the used in Microsoft.AspNet.OData. I got my code working using this.

Upvotes: 0

Ivan Samygin
Ivan Samygin

Reputation: 4571

OData (at least since v3) uses specific json to represent errors:

{
    "error": {
        "code": "A custom error code",
        "message": {
            "lang": "en-us",
            "value": "A custom long message for the user." 
        },
        "innererror": {
            "trace": [...],
            "context": {...}
        }
    }
}

Microsoft .Net contains Microsoft.Data.OData.ODataError and Microsoft.Data.OData.ODataInnerError classes to form OData error on a server side.

To form proper OData error response (HttpResponseMessage), that contains error details you can:

1) form and return HttpResponseMessage in controller's action using System.Web.OData.Extensions.HttpRequestMessageExtensions.CreateErrorResponse method

return Request.CreateErrorResponse(HttpStatusCode.Conflict, new ODataError { ErrorCode="...", Message="...", MessageLanguage="..." }));

2) throw HttpResponseException using the same method for creating HttpResponseMessage

throw new HttpResponseException(
    Request.CreateErrorResponse(HttpStatusCode.NotFound,  new ODataError { ErrorCode="...", Message="...", MessageLanguage="..." }));

3) throw custom typed exception and convert it using Web Api action filters

public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {
        if (context.Exception is CustomException)
        {
            var e = (CustomException)context.Exception;

            var response = context.Request.CreateErrorResponse(e.StatusCode, new ODataError
            {
                ErrorCode = e.StatusCodeString,
                Message = e.Message,
                MessageLanguage = e.MessageLanguage
            });
            context.Response = response;
        }
        else
            base.OnException(context);
    }
}

Upvotes: 28

Vladimir
Vladimir

Reputation: 7475

Use HttpResponseException,
e.g. throw new HttpResponseException(HttpStatusCode.NotFound);.
Details can be found here.

Upvotes: 1

Related Questions