wcf / ajax模糊错误“错误”

I'm having trouble using jQuery AJAX to retrieve data from a WebGet function in an "AJAX-enabled WCF Service". The service code is shown below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;

namespace SPA
{
  [ServiceContract(Namespace = "")]
  [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
  public class db
  {
    // To use HTTP GET, add [WebGet] attribute. (Default ResponseFormat is WebMessageFormat.Json)
    // To create an operation that returns XML,
    //     add [WebGet(ResponseFormat=WebMessageFormat.Xml)],
    //     and include the following line in the operation body:
    //         WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
    [WebGet]
    [OperationContract]
    public IEnumerable<Geofence> GetGeofences()
    {
      WebOperationContext.Current.OutgoingResponse.ContentType = "text/json";
      var dc = new AtomnetDataContext();
      return dc.Geofences;
    }

    // Add more operations here and mark them with [OperationContract]
  }
}

And this is the code that attempts to call it:

$(function () {
  $.get("db.svc/GetGeofences", alert);
});

Placing a breakpoint inside the service method code reveals that it is indeed invoked. I confirmed that data is successfully fetched by realising dc.Geofences.ToArray() into a variable, not shown in the sample. Geofence is a Linq2sql generated type.

Converting the invocation to an explicit ajax call $.ajax({ ... }); returns an error object to the error function, but the message contained therein merely says "error", which is less than instructive.

Inspecting the network traffic using the IE10 equivalent to Firebug reveals that the call is "(Aborted)". This problem has to be service configuration, since the call gets as far as trying to return a value.

It appears that there is a Serialisation exception, then a communication exception which is probably consequential.

A first chance exception of type 'System.Runtime.Serialization.SerializationException' 
occurred in System.Runtime.Serialization.dll A first chance exception of type 
'System.ServiceModel.CommunicationException' occurred in System.ServiceModel.Web.dll

The root of all the problems was the fact that after adding the badly named entity SiteData to the model, I renamed it to Geofences. If you do this, you get the problems I describe. If you don't, everything's hunky dory.

Another problem that I still face is that when I include other entities that have relationships to SiteData that the designer recognises and implements, this also produces serialisation errors. Manually removing the relationships sorts it out, but I have the strongest feeling you can probably also fix this with a config setting. Anyone know how?

Oh, and you can't pass alert as the success function, passing a native function like this seems to discombobulate jquery. The example on p70 of the O'reilly jQuery Pocket Reference doesn't work. Not with IE10, at any rate.

The serialisation errors are a result of cycles. A bit more digging produced this message:

System.Runtime.Serialization.SerializationException occurred
  HResult=-2146233076
  Message=Object graph for type 'SPA.SiteGroup' contains cycles and cannot be 
  serialized if reference tracking is disabled.
  Source=System.Runtime.Serialization
  StackTrace:
       at System.Runtime.Serialization.XmlObjectSerializerWriteContext.OnHandleReference(XmlWriterDelegator xmlWriter, Object obj, Boolean canContainCyclicReference)
  InnerException: 

The question now is how to enable reference tracking.

This ought to be an attribute of the endpoint behaviour.

<behaviors>
  <endpointBehaviors>
    <behavior name="SPA.dbAspNetAjaxBehavior">
      <enableWebScript />
      <dataContractSerializer 
        preserveObjectReferences="true"
        ignoreExtensionDataObject="false" 
        maxItemsInObjectGraph="99" />
    </behavior>
  </endpointBehaviors>
</behaviors>

Unfortunately, you can't do anything so reasonable because System.ServiceModel.Configuration.DataContractSerializerElement doesn't expose the preserveObjectReferences constructor parameter for the DataContractSerializer.

The conspiracy theorist in me suspects that this is no accident. The Entity Framework team doesn't like Linq2Sql because it embarrasses them by out performing EF by a country mile.

I found another workaround: if you don't want to delete the associations, you can select them and set the Child Property property to False. This inhibits the generation of a child objects collection and then you don't have a circular reference.