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
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);
}
}
Use HttpResponseException
,
e.g. throw new HttpResponseException(HttpStatusCode.NotFound);
.
Details can be found here.
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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With