序列化由自引用只读属性引起的循环异常

时间:2010-12-01 19:07:28

标签: .net serialization datacontract circular-reference

当尝试从JSON asp.net 3.5SP1 WebService(不是WCF,带有 scriptservice 属性的经典asp.net WebService)返回一个对象时,我有一个“一个循环引用是序列化'Geo.Bound'“类型的对象时检测到错误,该错误由自引用只读属性引起:

简化代码:

Namespace Geo
<DataContract(Namespace:="Geo", IsReference:=True)> _
Public Class Bound

 <DataMember(Name:="sw", IsRequired:=False)> _
 Public SouthWestCoord As Double


 Public Sub New()
  SouthWestCoord = 1.5#
 End Sub

 <IgnoreDataMember()> _
 Public ReadOnly Property Bds() As Bound
  Get
   Return Me
  End Get
 End Property

End Class
End Namespace
  • 我想保留Read-Only属性,因为它用于实现接口。
  • 向Bound类添加“IsReference:= True”属性不会改变任何内容。
  • 如果我使用DataContractJsonSerializer(在webservice的上下文之外,就像这个例子:link text),它可以工作,我有一个正确的JSON。
  • 如果我删除“Bds”只读属性就可以了!!

我不明白为什么!它是一个readonly属性,没有DataMember属性,带有IgnoreDatamember属性,它不应该被序列化!

如何保留“Bds”属性,并摆脱循环引用异常?

谢谢!

2 个答案:

答案 0 :(得分:1)

这是一个例子,有效(抱歉C#)

  1. 定义的课程:

    [DataContract(Namespace = "Geo")]
    public class Bound
    {
        [IgnoreDataMember]
        public Bound { get { return this; } }
    
    
       [DataMember]
       public string Name { get; set; }
    }
    
  2. 创建服务接口(和实现)

    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json)]
        Bound DoWork();
    }
    
    
    public class Service1 : IService1
    {
        public Bound DoWork()
        {
            return new Bound { Name = "Test Name" };
        }
    }
    
  3. 编辑app.config的system.serviceModel部分

    <behaviors>
      <endpointBehaviors>
        <behavior name="endBeh">
          <enableWebScript/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service name="JsonSerializationTest.Service1">
        <endpoint address="" binding="webHttpBinding" behaviorConfiguration="endBeh" contract="JsonSerializationTest.IService1" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8732/Design_Time_Addresses/JsonSerializationTest/Service1/"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    
  4. 在Program.cs中启动服务主机

    using (var sh = new ServiceHost(typeof(Service1)))
    {
        sh.Open();
        Console.WriteLine("Opened");
        Console.ReadLine();
    }
    
  5. 启动程序,打开浏览器,键入http://localhost:8732/Design_Time_Addresses/JsonSerializationTest/Service1/DoWork并收到Json-ed测试对象:

    {"d":{"__type":"Bound:Geo","Name":"Test Name"}}
    

    PS:WebInvokeAttribute位于 System.ServiceModel.Web.dll 程序集中。

答案 1 :(得分:0)

您正在获取循环引用因为它是类绑定,引用了Bound类型的属性。这意味着它是一个无穷无尽的供应的Bound对象。

不确定为什么IgnoreDataMember无法正常工作。如果我有任何想法,我会给这个更多的时间并更新我的答案。