7heViking
7heViking

Reputation: 7577

OData cannot serialize a null resource

When the arguments given in an OData query does not find a result - how will you be handling the returned null value. I get this exception if it happends that there are no retult or I simply return null without ever searching.

Error: Cannot serialize a null 'Resource'

An unhandled exception was thrown by the application. System.Runtime.Serialization.SerializationException: Cannot serialize a null 'Resource'. at Microsoft.AspNet.OData.Formatter.Serialization.ODataResourceSerializer.WriteObjectInline(Object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext) at Microsoft.AspNet.OData.Formatter.Serialization.ODataResourceSerializer.WriteObject(Object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext) at Microsoft.AspNet.OData.Formatter.ODataOutputFormatterHelper.WriteToStream(Type type, Object value, IEdmModel model, ODataVersion version, Uri baseAddress, MediaTypeHeaderValue contentType, IWebApiUrlHelper internaUrlHelper, IWebApi

I would expect it to return an empty result and a 204 code - but it returns an empty result with a 200 code and throws the exception in the console.

Here is some sample code from the controller:

[EnableQuery]
[ODataRoute("Topic/{id}")]
public TopicDto? GetTopic(string id)
{
    return _dbTableContext.Topic.Find(id);
}

enter image description here

Upvotes: 3

Views: 2073

Answers (2)

abhijat_saxena
abhijat_saxena

Reputation: 970

In my case - I had an object where one of it's property was a List<> and it was set to null. When I returned this object back - from response to my Serializer - it failed with the above exception.
Simply initializing the property to a new List<> would solve your problem.

Upvotes: 0

prd
prd

Reputation: 2321

Try returning an IActionResult instead of a nullable TopicDto from your controller methods, as this leaves you with more flexibility regarding HTTP responses.

The same principle applies to ASP.NET but with IHttpActionResult as the return type.

TopicsController.cs

[ODataRoutePrefix("topics")]
public class TopicsController : ODataController
{
    private static readonly TopicViewModel[] _topics = new TopicViewModel[]
    {
        new TopicViewModel { Id = 1, Title = "Topic A"},
        new TopicViewModel { Id = 2, Title = "Topic B"},
        new TopicViewModel { Id = 3, Title = "Topic C"}
    };

    [EnableQuery]
    [ODataRoute("{id}")]
    public IActionResult Get(int id)
    {
        var topic = _topics.FirstOrDefault(x => x.Id == id);

        if (topic == null)
        {
            return NotFound();
        }

        return Ok(topic);
    }
}

API Test using cURL

curl -i "https://localhost:44391/odata/topics(1)"
HTTP/2 200
content-type: application/json; odata.metadata=minimal; odata.streaming=true
server: Microsoft-IIS/10.0
odata-version: 4.0
x-powered-by: ASP.NET
date: Fri, 21 Aug 2020 09:28:42 GMT

{"@odata.context":"https://localhost:44391/odata/$metadata#Topics/$entity","Id":1,"Title":"Topic A"}
curl -i "https://localhost:44391/odata/topics(0)"
HTTP/2 404
server: Microsoft-IIS/10.0
x-powered-by: ASP.NET
date: Fri, 21 Aug 2020 09:28:54 GMT

Upvotes: 3

Related Questions