Receiving 406 Status Code error when using MVC4+OData+Queryable

1.1k views Asked by At

I'm stuck with the simplest OData scenario on MVC4 and .NET4.
This is my WebApiConfig file:

        config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
        ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
        builder.EntitySet<Client>("Client");

        config.Routes.MapODataRoute(
          routeName: "odataapi",
          routePrefix: "api",
          model: builder.GetEdmModel()
        );
        config.EnableQuerySupport();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
        config.EnableQuerySupport();
        config.EnableSystemDiagnosticsTracing();
        config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling =
              Newtonsoft.Json.PreserveReferencesHandling.All;

And this is my controller:

public class ODataGridController : ODataController
{
    DevEntities dbcontext = EFRepository.Create<DevEntities>(); 

    [HttpGet]
    [Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
    public IQueryable<Client> Get()
    {
        var model = dbcontext.Client.AsQueryable();
        return model;
    }
}

This is my trace data from VisualStudio:

iisexpress.exe Information: 0 : Request, Method=GET, Url=[some_link]/api/ODataGrid, Message='[some_link]/api/ODataGrid'
iisexpress.exe Information: 0 : Message='Will use same 'JsonMediaTypeFormatter' formatter', Operation=JsonMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use same 'XmlMediaTypeFormatter' formatter', Operation=XmlMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use same 'FormUrlEncodedMediaTypeFormatter' formatter', Operation=FormUrlEncodedMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use same 'JQueryMvcFormUrlEncodedFormatter' formatter', Operation=JQueryMvcFormUrlEncodedFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use same 'JsonMediaTypeFormatter' formatter', Operation=JsonMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use same 'XmlMediaTypeFormatter' formatter', Operation=XmlMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use same 'FormUrlEncodedMediaTypeFormatter' formatter', Operation=FormUrlEncodedMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use same 'JQueryMvcFormUrlEncodedFormatter' formatter', Operation=JQueryMvcFormUrlEncodedFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='ODataGrid', Operation=DefaultHttpControllerSelector.SelectController
iisexpress.exe Information: 0 : Message='Will use new 'ODataMediaTypeFormatter' formatter', Operation=ODataMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='MvcApplication6.Services.ODataGridController', Operation=DefaultHttpControllerActivator.Create
iisexpress.exe Information: 0 : Message='MvcApplication6.Services.ODataGridController', Operation=HttpControllerDescriptor.CreateController
iisexpress.exe Information: 0 : Message='Selected action 'Get()'', Operation=ApiControllerActionSelector.SelectAction
iisexpress.exe Information: 0 : Message='Selected action 'Get()'', Operation=ODataActionSelector.SelectAction
iisexpress.exe Information: 0 : Message='Selected action 'Get()'', Operation=ODataActionSelector.SelectAction
iisexpress.exe Information: 0 : Operation=HttpActionBinding.ExecuteBindingAsync
iisexpress.exe Information: 0 : Operation=HttpActionBindingTracer.ExecuteBindingAsync
iisexpress.exe Information: 0 : Operation=HttpActionBindingTracer.ExecuteBindingAsync
iisexpress.exe Information: 0 : Operation=QueryableAttribute.ActionExecuting
'iisexpress.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_32\System.Data.OracleClient\v4.0_4.0.0.0__b77a5c561934e089\System.Data.OracleClient.dll', Symbols loaded.
'iisexpress.exe' (Managed (v4.0.30319)): Loaded 'EntityFrameworkDynamicProxies-MvcApplication6'
iisexpress.exe Information: 0 : Message='Action returned 'SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[status] AS [status], 
    [Extent1].[firstname] AS [firstname], 
    [Extent1].[lastname] AS [lastname], 
    [Extent1].[ssn] AS [ssn], 
    [Extent1].[addr_city] AS [addr_city], 
    [Extent1].[addr_street] AS [addr_street], 
    [Extent1].[addr_home] AS [addr_home], 
    [Extent1].[phone_cell] AS [phone_cell], 
    [Extent1].[phone_home] AS [phone_home], 
    [Extent1].[phone_spose] AS [phone_spose], 
    [Extent1].[work_name] AS [work_name], 
    [Extent1].[work_phone] AS [work_phone], 
    [Extent1].[fax] AS [fax], 
    [Extent1].[email] AS [email], 
    [Extent1].[facebook] AS [facebook], 
    [Extent1].[remark] AS [remark], 
    [Extent1].[office_id] AS [office_id], 
    [Extent1].[picture] AS [picture]
    FROM [dbo].[Client] AS [Extent1]'', Operation=HttpActionDescriptorTracer.ExecuteAsync
iisexpress.exe Information: 0 : Message='Will use new 'ODataMediaTypeFormatter' formatter', Operation=ODataMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use new 'ODataMediaTypeFormatter' formatter', Operation=ODataMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use new 'ODataMediaTypeFormatter' formatter', Operation=ODataMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use new 'ODataMediaTypeFormatter' formatter', Operation=ODataMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use new 'ODataMediaTypeFormatter' formatter', Operation=ODataMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use new 'ODataMediaTypeFormatter' formatter', Operation=ODataMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use same 'FormUrlEncodedMediaTypeFormatter' formatter', Operation=FormUrlEncodedMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use same 'JQueryMvcFormUrlEncodedFormatter' formatter', Operation=JQueryMvcFormUrlEncodedFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use same 'ODataMediaTypeFormatter' formatter', Operation=ODataMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use same 'ODataMediaTypeFormatter' formatter', Operation=ODataMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use same 'ODataMediaTypeFormatter' formatter', Operation=ODataMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use same 'ODataMediaTypeFormatter' formatter', Operation=ODataMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use same 'ODataMediaTypeFormatter' formatter', Operation=ODataMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use same 'ODataMediaTypeFormatter' formatter', Operation=ODataMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use same 'FormUrlEncodedMediaTypeFormatter' formatter', Operation=FormUrlEncodedMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Will use same 'JQueryMvcFormUrlEncodedFormatter' formatter', Operation=JQueryMvcFormUrlEncodedFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Selected formatter='none', content-type='none'', Operation=DefaultContentNegotiator.Negotiate
iisexpress.exe Information: 0 : Message='Selected formatter='none', content-type='none'', Operation=PerRequestContentNegotiator.Negotiate
iisexpress.exe Information: 0 : Message='Selected formatter='none', content-type='none'', Operation=PerRequestContentNegotiator.Negotiate
iisexpress.exe Information: 0 : Operation=ApiControllerActionInvoker.InvokeActionAsync, Status=406 (NotAcceptable)
iisexpress.exe Information: 0 : Operation=QueryableAttribute.ActionExecuted, Status=406 (NotAcceptable)
iisexpress.exe Information: 0 : Operation=ODataGridController.ExecuteAsync, Status=406 (NotAcceptable)
iisexpress.exe Information: 0 : Response, Status=406 (NotAcceptable), Method=GET, Url=[some_link]/api/ODataGrid, Message='Content-type='none', content-length=unknown'
iisexpress.exe Information: 0 : Operation=ODataGridController.Dispose

dbcontext is the regular EF6 context.
When I execute request I receive 406 error.
I checked all available information and see no reason why it doesn't work.
May be OData started working since MVC5 and in MVC4 it still was too buggy?

2

There are 2 answers

0
mirik On BEST ANSWER

The problem was here:

config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.All;

I changed All no None and everything has been solved. This was also problematic:

builder.EntitySet<Client>("Client");
1
Sam Xu On
  1. In Web API OData, the name of the convention controller class follows the template:

    public class {EntitySetName}Controller : ODataController
    {
        // ...
    }
    

    From your model builder as:

    builder.EntitySet<Client>("Client");
    

    The controller should be named as "ClientController".

  2. You add a Web API OData route as

    config.Routes.MapODataRoute(
          routeName: "odataapi",
          routePrefix: "api",
          model: builder.GetEdmModel());
    

    but from the trace, your request uri is: Url=[some_link]/api/ODataGrid It doesn't match the above odata route, instead it matches your second route:

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional });
    

    Although it can route and invoke the "Get" method, but "DefaultApi" route can't serialize the result returned from "Get" method. So, the response is "406".

  3. You can do like below to make it work:

    Change the ODataGridController as ClientController;
    Remove the MapHttpRoute(...) call;
    Send Request as : Url=[some_link]/api/Client