我差不多完成了写我的服务,而且我花了几个小时进行测试。但是,无论我怎么努力,我都会得到一个特定服务的一个特定方法(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以获取更多详细信息。
答案 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解决循环引用问题。我在那里添加了一个答案,向您展示如何在单独的文件中执行此操作。看看这是否有助于你。