WCF中的数据合同和循环引用

时间:2016-07-01 12:59:06

标签: c# .net wcf

我上面有课,但只有 SayHello 可以使用。你知道原因吗?

public class Service1 : IService1
{
    public Department GetDepartment()
    {
        Department d1 = new Department() { DepartmentName = "dep1" };

        d1.employees = new List<Employee>() {
                new Employee() {
                    username="user1",
                    department=d1
                },
                new Employee() {
                     username="user2",
                    department=d1
                }
            };

        return d1;
    }

    public string SayHello(string username)
    {
        return "Hello " + username + "!";
    }
}

[DataContract]
public class Department
{
    [DataMember]
    public string DepartmentName { get; set; }
    [DataMember]
    public List<Employee> employees { get; set; }
}

[DataContract]
public class Employee
{
    [DataMember]
    public string username { set; get; }
    [DataMember]
    public Department department { get; set; }
}

SayHello可以正常运行,但GetDepartment失败,错误如下:

*收到http://localhost:8080/的HTTP响应时发生错误。这可能是由于服务端点绑定不使用HTTP协议。这也可能是由于服务器中止HTTP请求上下文(可能是由于服务关闭)。请参阅服务器日志以获取更多详 服务器堆栈跟踪:    在

System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at IService1.GetDepartment()
   at Service1Client.GetDepartment()
Inner Exception:
The underlying connection was closed: An unexpected error occurred on a receive.
   at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
Inner Exception:
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)
Inner Exception:
An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)*

2 个答案:

答案 0 :(得分:1)

按照此处的说明将IsReference=true添加到DataContractData Contracts and Circular References

[DataContract(IsReference=true)]
public class Department
{
    [DataMember]
    public string DepartmentName { get; set; }
    [DataMember]
    public List<Employee> employees { get; set; }
}

[DataContract(IsReference=true)]
public class Employee
{
    [DataMember]
    public string username { set; get; }

    [DataMember]
    public Department department { get; set; }

}

测试客户端显示GetDepartment()方法的成功执行:

enter image description here

答案 1 :(得分:0)

启用WCF跟踪可能会告诉您需要了解的所有信息。 我希望您可能会在详细级别看到一些内容,一旦您在跟踪查看器工具中打开WCF跟踪,它就会为您提供更多异常信息。我最初的怀疑是你可能需要为一个或另一个类声明KnownTypes。包含Employee和Employee包含Department的Department的循环特性也可能导致序列化问题。我不记得以前我是否已经这样做了。

在这里查看有关KnownTypes和WCF的更多信息:

https://msdn.microsoft.com/en-us/library/ms730167(v=vs.110).aspx