Search code examples
asp.net-web-api2odataowin

Serialization error when specifying $select on ODataController endpoint


I've been developing a RESTful web service using Web API 2 and OWIN. Originally my controllers inherited from ApiController, and the GET actions supported OData filtering/queries i.e. marked with [EnableQuery].

We've now decided to look at whether it's feasible to expose a true OData service, and so make our controllers inherit from ODataController instead of ApiController. While this seems to be working well for the most part, $select no longer works.

public class BaseController : ODataController
{
    ... some properties here, not related to issue...
}


public class EmployeesController : BaseController
{
   private readonly AppDbContext _context = new AppDbContext();

   [EnableQuery]
   public IQueryable<Employee> Get()
   {
       return _context.Employees;
   }
   ...
}

The error I'm seeing is:

{
  "error": {
    "code": "",
    "message": "An error has occurred.",
    "innererror": {
      "message": "'DbQuery`1' cannot be serialized using the ODataMediaTypeFormatter.",
      "type": "System.Runtime.Serialization.SerializationException",
      "stacktrace": "   at System.Web.OData.Formatter.ODataMediaTypeFormatter.GetSerializer(Type type, Object value, ODataSerializerProvider serializerProvider)\r\n   at System.Web.OData.Formatter.ODataMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders)\r\n   at System.Web.OData.Formatter.ODataMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Owin.HttpMessageHandlerAdapter.<BufferResponseContentAsync>d__13.MoveNext()"
    }
  }
}

I'm puzzled how this works with ApiController, but not with ODataController! Is there something I'm missing?

Cheers!


Solution

  • Ok, I've figured out what was happening:

    I tried to update my OData packages to the latest version for OData v4 support. The Microsoft .Net OData library namespaces have changed between OData v3 (System.Web.Http.OData) and v4 (System.Web.OData). I had somehow managed to mix these libraries in such a way that I was referencing the EnableQuery attribute in the old OData library, which caused the serialization issue.

    Not an obvious problem to track down - it's not obvious what's happening when the attributes have the same name but are in different namespaces and in fact belong to entirely different versions!