I've searched this intensive but can't get it to work.
I've haven an Web AP2 OData API and need to return a custom error class.
Here is what I have:
public class Error
{
public string Code { get; set; }
public string Message { get; set; }
}
In Global.asax.cs
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
GlobalConfiguration.Configuration.MessageHandlers.Add(new MessageInterceptor());
}
public class MessageInterceptor : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return base.SendAsync(request, cancellationToken).ContinueWith(
task =>
{
var body = task.Result.Content.ReadAsStringAsync().Result;
var resultObj = JsonConvert.DeserializeObject(body.Replace("value", "Results"));
task.Result.Content = new ObjectContent(typeof(object), resultObj, new JsonMediaTypeFormatter());
return task.Result;
}, cancellationToken);
}
}
In WebApiConfig,cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new HandleApiExceptionAttribute());
}
}
public class HandleApiExceptionAttribute : ExceptionFilterAttribute, IExceptionFilter
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is Error)
{
var res = context.Exception.Message;
//Define the Response Message
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent(res),
ReasonPhrase = res
};
//Create the Error Response
context.Response = response;
}
}
public class OrdersController : ODataControllerA controller
{
private Context db = new Context();
// GET: odata/Orders
[Queryable]
public IQueryable<Orders> GetOrders(ODataQueryOptions<Orders> opts)
{
<some code producing error>
Error theError = new Error()
{
Code = "1000",
Message = "Geen filter gespecificeerd"
};
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.BadRequest, theError);
//return Request.CreateResponse(HttpStatusCode.BadRequest, theError);
throw new HttpResponseException(response);
}
When I try this this crashes in the MessageInterceptor.
This is there because a third party consuming the API want's it in the specific format.
When the code runs correct it returns results{}
On error it should return Error{code:, message: }
Anyone ideas?
Jeroen
This is what I came up with:
I changed the controller to:
[Queryable, BasicAuthentication]
public IHttpActionResult GetOrders(ODataQueryOptions<Orders> opts)
{
else
{
Error theError = new Error()
{
Code = "1000",
Message = "Geen filter gespecificeerd"
};
return new ErrorResult(theError, Request);
}
return Ok(resultList);
}
Using this class:
public class ErrorResult : IHttpActionResult
{
Error _error;
HttpRequestMessage _request;
public ErrorResult(Error error, HttpRequestMessage request)
{
_error = error;
_request = request;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
List<Error> _errorList = new List<Error>();
_errorList.Add(_error);
error err = new error()
{
errors = _errorList
};
var response = new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new ObjectContent<error>(err, new JsonMediaTypeFormatter()),
RequestMessage = _request
};
return Task.FromResult(response);
}
}
public class Error
{
public string Code { get; set; }
public string Message { get; set; }
}
public class error
{
public List<Error> errors { get; set; }
}