WCF REST service won't return children of Enti

2019-05-06 03:10发布

问题:

I have written a WCF service with the REST template that has the defaultOutgoingResponseFormat set to Json. Under that, I have built a simple entity model using Entity Framework and ObjectContext, in order to pass around custom POCO entities.

If I pass a single entity, the system works as expected. If I add children to the entity, the REST response is blank. In the debugger, the entity is populated correctly, but the service itself returns nothing at all.

So, for instance, I have a Trip.Get() method. The WCF code looks like this:

[WebGet(UriTemplate = "{id}", ResponseFormat = WebMessageFormat.Json)]
public Model.Trip Get(string id)
{
    Model.Trip fetchedTrip = null;
    try
    {
        fetchedTrip = Library.Trip.Get(new Guid(id));
    }
    catch (Exception ex)
    {
        Debug.Write(ex.Message);
    }
    return fetchedTrip;
}

Library.Trip.Get looks like this in the working version:

public static Model.Trip Get(Guid tripId)
{
    using (Model.POCOTripContext context = new Model.POCOTripContext())
    {
        var tripEntity = context.Trips.FirstOrDefault(c => c.Id == tripId) ?? new Model.Trip();
        return tripEntity;
    }
}

This returns the expected result, which looks like this:

{"ArrivalDate":"/Date(1334203200000-0400)/","DepartureDate":"/Date(1334721600000-0400)/","Id":"d6413d96-fe1f-4b1c-ae7a-3bbf516cdc2f","Name":"Test 123","Photos":null,"PlacesOfInterest":null,"WhereTo":"Orlando, FL"}

If I change the Library method to add in the children, however, the REST service returns a blank value. Nothing, nada.

public static Model.Trip Get(Guid tripId)
{
    using (Model.POCOTripContext context = new Model.POCOTripContext())
    {
        var tripEntity = context.Trips.Include("PlacesOfInterest").Include("Photos").Include("PlacesOfInterest.PoiAttributes").FirstOrDefault(c => c.Id == tripId) ?? new Model.Trip();
        return tripEntity;
    }
}

The debugger, in the WCF service on the return statement, shows that the entity is fully and correctly populated.

I am certain that I am just missing some magic attribute, and am hoping that someone who has dome this before might be able to help me out!

回答1:

According to your small test with removing back tracking navigation property you have problem with serialization to JSON. Default serialization is not able to track object references so when it starts serializing your Trip it follows navigation property to points of interest and in first of them it finds reference to Trip. Because it doesn't track references it follows the navigation property and serializes trip again (and again follows his navigation properties) => infinite loop.

You must either remove your back tracking navigation property as you did in test or you must tell serializer either to track references or to exclude that property from serialization (well I'm not sure what the first option will do in case of JSON). I guess you are using default WCF serialization so either:

  • Mark each entity with [DateContract(IsReference = true)] and each serialized property with [DataMember] attributes to start tracking references.
  • Or mark back tracking navigation property with [IgnoreDataMember] attribute to exclude the property from serialization