Reputation: 583
I'm learning Web Api and have bumped into the following issue. Similar to this question.
My exceptions are still returning as XML in Chrome, but JSON in IE. The exceptions are thrown as XML when inheriting from the ODataController but are correctly thrown as JSON when inheriting from ApiController.
My WebApiConfig class:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.Filters.Add(new NotImplementedExceptionFilterAttribute());
config.Filters.Add(new MethodAttributeExceptionHandling());
config.Services.Replace(typeof(IHttpActionInvoker), new CustomApiControllerActionInvoker());
// Web API routes
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<EventType>("EventTypes");
config.Routes.MapODataRoute("ODataRoutes", "api", builder.GetEdmModel());
//Route Configuration
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}"
);
var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
}
I have a CustomApiControllerActionInvoker verbatim from: http://www.codeproject.com/Articles/733512/Exception-Handling-in-WebAPI
My TestController inheriting from ApiController:
public HttpResponseMessage GetGlobalErrorMessage()
{
int i = 0;
var val = 10 / i;
return new
HttpResponseMessage(HttpStatusCode.OK);
}
returns JSON in Chrome:
{
"Message": "Oops some internal Exception. Please contact your administrator",
"ErrorCode": 500
}
However, if I inherit from ODataController with similar code:
[Queryable]
public IQueryable<EventType> Get()
{
int i = 0;
var val = 10 / i;
return _repo.EventTypes();
}
I'm returned XML from the exception in Chrome:
<m:error xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<m:code/>
<m:message xml:lang="en-US">
Oops some internal Exception. Please contact your administrator
</m:message>
</m:error>
How do I force consistent content types for payloads as well as exceptions, still allowing flexibility for native content negotiation using OData Web Api?
Upvotes: 0
Views: 717
Reputation: 3503
As @Kiran said above, here is a working example
[ODataFormattingOnlyJSON]
public class BaseODataController
: ODataController
{
}
public class ODataFormattingOnlyJSONAttribute : ODataFormattingAttribute, IControllerConfiguration
{
void IControllerConfiguration.Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
{
base.Initialize(controllerSettings, controllerDescriptor);
//remove all the dirty non json formatters
var remove = controllerSettings.Formatters.Where(m => !m.SupportedMediaTypes.Any(t => t.MediaType.IndexOf("json", StringComparison.OrdinalIgnoreCase) >= 0)).ToArray();
foreach (var item in remove)
{
controllerSettings.Formatters.Remove(item);
}
}
}
Then all your controllers inherit from BaseODataController
Upvotes: 1
Reputation: 57989
The difference in response formats between these browsers is due to the kind of Accept
headers that they send. Depending on Accept
header, Web API runs content-negotiation and returns the appropriate response. ODataController
is special in that it does not use the formatters that regular ApiController
uses. Instead ODataController has a Per-Controller Configuration
attribute called ODataFormattingAttribute
from which you can derive to build a custom list of formatters through its CreateODataFormatters
method and use this attribute on all your ODataControllers.
Upvotes: 0