3

I was writing a Rest endpoint and for some reason the rest calls themselves kept returning empty content even though debugging the code revealed that the Response's Content was defined as I expected it to be. The same problem did not manifest itself for similar calls. Eventually, I realized that the difference between the calls that worked and the calls that failed was that the unsuccessful calls attempted to return recursive (types with public properties/fields of that type) or mutually recursive types while the successful calls did not. As a minimal example of the problem I encountered:

[RoutePrefix("")]
public class LoopyController
{
    public class Loopy
    {
        public Loopy Self {get; set;}
    }

    [HttpGet]
    [Route("loopy")]
    public HttpResponseMessage LoopyCall()
    {
        Loopy loopy = new Loopy();
        loopy.Self = loopy;
        return Request.CreateResponse(loopy)
    }
}

A GET call on the loopy endpoint returns an empty response. I would expect it to either hang or throw an exception. I would like to know why ASP.Net exhibits this behavior. I recognize that a solution to this problem is to modify the return value so that it is no longer recursive in anyway, but would like to know if there is a cleaner method of resolving this issue.

Edit:

There's been discussion in the comments about my use of the term 'recursive type'. I am confident going by https://en.wikipedia.org/wiki/Recursive_data_type that Loopy is a recursive type. However, the problem is not so much that the type Loopy is recursive but that the object loopy has a circular reference. The following endpoint:

[HttpGet]
[Route("notsoloopy")]
public HttpResponseMessage NotSoLoopy()
{
    Loopy notSoLoopy = new Loopy();
    notSoLoopy.Self = null;
    return Request.CreateResponse(notSoLoopy);
}

returns the response {} in reply to a GET request. Of course Loopy being recursive enables loopy's having a circular reference.

12
  • 3
    This is not recursion, it is a circular reference. WebAPI json formatter is set to ignore circular references by default. Even if you're using XML I am thinking (but not sure) this is ignored anyway. This article might provide some insight: blogs.msdn.com/b/hongyes/archive/2012/09/04/… Commented Nov 10, 2015 at 15:40
  • 2
    @Dmitriy -- this is a known use of the term 'recursive' (see en.wikipedia.org/wiki/Recursive_data_type). Thank you for the blog link, it was exactly what I was looking for! Commented Nov 10, 2015 at 15:43
  • 1
    Semantics :) I rather prefer to make a distinction between the two, since in this case it is the same instance not just the same type. Commented Nov 10, 2015 at 15:44
  • 2
    Recursive data type does not mean instances of that type will have circular references (i.e. valid linked list is recursive type but no circular references, but you can use the same type to built circular buffer) Commented Nov 10, 2015 at 15:48
  • 1
    Also this is very much a circular reference and not a recursive type, from the link in wiki page you added: data type for values that may contain other values of the same type. Note type not same object. Commented Nov 10, 2015 at 15:54

1 Answer 1

3

This is a circular reference. WebAPI json formatter is set to ignore circular references by default. Even if you're using XML I am thinking (but not sure) this is ignored anyway. This article might provide some insight:

Json.net serializer (the serializer used in web api) supports to ignore circular reference on global setting.

Sign up to request clarification or add additional context in comments.

2 Comments

Just commented the relevant part of the article and tidied up a bit :)
Thanks! Looks much better :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.