2

当试图从 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
  • 我想保留只读属性,因为它用于实现接口。
  • 向 Bound 类添加“IsReference:=True”属性不会改变任何内容。
  • 如果我使用 DataContractJsonSerializer (在 web 服务的上下文之外,像这个例子:链接文本),它可以工作并且我有一个正确的 JSON。
  • 如果我删除“Bds”只读属性,它就可以工作!

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

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

谢谢 !

4

2 回答 2

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();
    }
    

启动程序,打开浏览器,输入http://localhost:8732/Design_Time_Addresses/JsonSerializationTest/Service1/DoWork并收到 Json-ed 测试对象:

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

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

于 2010-12-01T20:55:41.220 回答
0

您正在获得循环引用,因为它是 Bound 类,并引用了 Bound 类型的属性。这意味着它是无穷无尽的 Bound 对象。

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

于 2010-12-01T19:14:01.317 回答