WCF服务调用错误 - 接收HTTP响应时出错

时间:2013-12-18 17:40:30

标签: c# wcf http exception request

我差不多完成了写我的服务,而且我花了几个小时进行测试。但是,无论我怎么努力,我都会得到一个特定服务的一个特定方法(code visible here

的错误

一切正常,但Cinema.Server.ShowController的Get()和GetAll()方法除外。从代码中可以看出,Show是一个复杂的对象,我需要它的传输,架构不能改变。

每当我调用这两个函数时,如果有任何Show的数据库条目,它将抛出以下错误消息:

  

接收HTTP响应时发生错误   http://localhost:8090/ShowService。这可能是由于服务   端点绑定不使用HTTP协议。这也可能是应该的   到服务器中止的HTTP请求上下文(可能是由于   关闭服务)。有关详细信息,请参阅服务器日志。

(包含可用堆栈跟踪的完整消息here

由于除此之外没有来自WCF的错误报告(并且在客户端抛出此异常),我不知道问题是什么。有人可以开导我吗?

更新

所以在一些SvcTracing之后,这是实际的例外:

  

尝试序列化参数时出错   http://tempuri.org/:GetAllResult。 InnerException消息是'Type   'System.Data.Entity.DynamicProxies.Show_B50FB72FE59AC01FA537205B27B30F94605CB1F39BB27C2F1BBB00EF9A720361'   与数据合同名称   'Show_B50FB72FE59AC01FA537205B27B30F94605CB1F39BB27C2F1BBB00EF9A720361:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies'   不是预期的。考虑使用DataContractResolver或添加任何   静态地知道已知类型列表的类型 - 例如,   通过使用KnownTypeAttribute属性或将它们添加到   传递给DataContractSerializer的已知类型列表。'。请参阅   InnerException以获取更多详细信息。

3 个答案:

答案 0 :(得分:2)

将它放在客户端的配置文件中:

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel" switchValue="Information, ActivityTracing" propagateActivity="true">
        <listeners>
          <add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="Logger.xml" />
        </listeners>
      </source>
    </sources>

  </system.diagnostics>

运行客户端几次获取错误,并确认exe文件夹中有一个logging.xml文件。

下载适用于您的操作系统的Windows SDK,然后运行SvcTraceViewer,将其指向xml文件。如果这没有帮助,请将XML放入服务器的配置中并重复。

不能保证给出答案,但可以提供很大的帮助!

我在WCF中遇到的复杂结构的一个缺陷是循环引用:一个onject包含一个子列表;每个子项包含其父项的引用(序列化为副本)。父级的序列化副本包含子级列表等等。

干杯 -

答案 1 :(得分:2)

您正在WCF服务中使用Entity Framework,并且您正在返回从数据库中检索的实体。 EF动态创建您的类的代理子类。 WCF不知道如何处理代理子类。

这篇文章有更多的detials: http://msdn.microsoft.com/en-us/library/vstudio/ee705457(v=vs.100).aspx

  

POCO代理类型不能直接序列化或反序列化   Windows Communication Foundation(WCF),因为   DataContractSerializer序列化引擎只能序列化和   反序列化已知类型。代理类型不是已知类型。更多   信息,请参阅工作中的序列化POCO代理部分   与POCO实体主题。要将POCO代理序列化为POCO实体,   使用ProxyDataContractResolver类将代理类型映射到POCO   序列化期间的类型。

由于某种原因,MS提供了ProxyDataContractResolver,但没有应用解析器的属性。本文介绍如何实现ApplyDataContractResolverAttribute以及如何将其应用于操作。

<强>更新

在处理循环引用时,通过WCF直接返回EF对象存在相关问题。假设A类与B类具有多对一的关系.A具有B的导航属性,B具有A的集合。这可以通过使用属性[DataContract(IsReference = true)]标记DataContract来处理,但是如果您正在传递EF对象,则可能不希望将DataContract和DataMember添加到模型中的每个类。相反,DataContractSerializer可以通过将preserveObjectReferences设置为true来为您处理此问题。 Sowmy Srinivasan有一篇很好的文章描述了如何做到这一点:Preserving Object Reference in WCF

结合使用ProxyDataContractResolver和preserveObjectReferences = true的两个方法,我想出了这些类:

public class ReferencePreservingProxyDataContractSerializerOperationBehavior
    : DataContractSerializerOperationBehavior
{
    public ReferencePreservingProxyDataContractSerializerOperationBehavior(
      OperationDescription operationDescription)
        : base(operationDescription) { }
    public override XmlObjectSerializer CreateSerializer(
      Type type, string name, string ns, IList<Type> knownTypes)
    {
        return CreateDataContractSerializer(type, name, ns, knownTypes);
    }

    private static XmlObjectSerializer CreateDataContractSerializer(
      Type type, string name, string ns, IList<Type> knownTypes)
    {
        return CreateDataContractSerializer(type, name, ns, knownTypes);
    }

    public override XmlObjectSerializer CreateSerializer(
      Type type, XmlDictionaryString name, XmlDictionaryString ns,
      IList<Type> knownTypes)
    {
        return new DataContractSerializer(type, name, ns, knownTypes,
            0x7FFF /*maxItemsInObjectGraph*/,
            false/*ignoreExtensionDataObject*/,
            true/*preserveObjectReferences*/,
            null/*dataContractSurrogate*/,
            new ProxyDataContractResolver());
    }
}

public class ReferencePreservingProxyDataContractFormatAttribute : Attribute, IOperationBehavior
{
    public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters)
    {
    }

    public void ApplyClientBehavior(OperationDescription description, System.ServiceModel.Dispatcher.ClientOperation proxy)
    {
        IOperationBehavior innerBehavior = new ReferencePreservingProxyDataContractSerializerOperationBehavior(description);
        innerBehavior.ApplyClientBehavior(description, proxy);
    }

    public void ApplyDispatchBehavior(OperationDescription description, System.ServiceModel.Dispatcher.DispatchOperation dispatch)
    {
        IOperationBehavior innerBehavior = new ReferencePreservingProxyDataContractSerializerOperationBehavior(description);
        innerBehavior.ApplyDispatchBehavior(description, dispatch);
    }

    public void Validate(OperationDescription description)
    {
    }
}

然后对于每个操作,我只应用[ReferencePreservingProxyDataContractFormatAttribute]

答案 2 :(得分:1)

我认为这部分是您的错误:

  

&#39;类型   &#39; System.Data.Entity.DynamicProxies.Show_B50FB72FE59AC01FA537205B27B30F94605CB1F39BB27C2F1BBB00EF9A720361&#39;   与数据合同名称   &#39; Show_B50FB72FE59AC01FA537205B27B30F94605CB1F39BB27C2F1BBB00EF9A720361:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies&#39;   不是预期的。

可以通过在您的上下文中将ProxyCreationEnabled设置为false来解决,例如:

cx = new CinemaContext();
cx.Configuration.ProxyCreationEnabled = false;

当然可能还有更多,但这可能有助于澄清实际问题。

然后,您可以查看this帖子,其中讨论了使用DataContract / DataMember解决循环引用问题。我在那里添加了一个答案,向您展示如何在单独的文件中执行此操作。看看这是否有助于你。