提问人:Adron 提问时间:10/24/2008 最后编辑:Adron 更新时间:9/6/2013 访问量:30145
常见 WCF 异常:连接意外关闭
Common WCF Exception : Connection Unexpectedly Closed
问:
我有三个项目。一个是 WCF 服务项目,一个是 WPF 项目,一个是 Microsoft 单元测试项目。我使用如下所示的数据对象设置了 WCF 服务项目:
[DataContract]
public enum Priority
{
Low,
Medium,
High
}
[DataContract]
public struct TimeInfo
{
[DataMember]
public Int16 EstimatedHours { get; set; }
[DataMember]
public Int16 ActualHours { get; set; }
[DataMember]
public DateTime StartDate { get; set; }
[DataMember]
public DateTime EndDate { get; set; }
[DataMember]
public DateTime CompletionDate { get; set; }
}
[DataContract]
public class Task
{
[DataMember]
public string Title { get; set; }
[DataMember]
public string Description { get; set; }
[DataMember]
public Priority Priority { get; set; }
[DataMember]
public TimeInfo TimeInformation { get; set; }
[DataMember]
public Decimal Cost { get; set; }
}
我的合同如下所示:
[ServiceContract]
public interface ITaskManagement
{
[OperationContract]
List<Task> GetTasks();
[OperationContract]
void CreateTask(Task taskToCreate);
[OperationContract]
void UpdateTask(Task taskToCreate);
[OperationContract]
void DeleteTask(Task taskToDelete);
}
当我尝试在 WPF 应用程序或单元测试项目中使用该服务时,请执行以下代码:
var client = new TaskManagementClient();
textBox1.Text = client.GetTasks().ToString();
client.Close();
我收到以下错误:“基础连接已关闭:连接意外关闭。
WPF 和单元测试项目的 app.config 如下所示:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_ITaskManagement" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:9999/TaskManagement.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ITaskManagement"
contract="TaskManagement.ITaskManagement" name="WSHttpBinding_ITaskManagement">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
WCF 服务的 web.config 如下所示:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="InternetBasedWcfServices.TaskManagementBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
<behavior name="InternetBasedWcfServices.ScheduleManagementBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="InternetBasedWcfServices.TaskManagementBehavior"
name="InternetBasedWcfServices.TaskManagement">
<endpoint address="" binding="wsHttpBinding" contract="InternetBasedWcfServices.ITaskManagement">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
<service behaviorConfiguration="InternetBasedWcfServices.ScheduleManagementBehavior"
name="InternetBasedWcfServices.ScheduleManagement">
<endpoint address="" binding="wsHttpBinding" contract="InternetBasedWcfServices.IScheduleManagement">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
这不是第一次发生这种情况,我猜这是配置问题。但每次我通常都会把我的服务吹走,然后把它放回去,或者创建一个新的服务项目。然后一切都很好。如果有人有任何想法,那就太棒了。感谢。
**
更新:我添加了更多评论 我对这个问题的疑难解答。 当有答案可用时,如果 答案未发布,我会将其添加为 官方的“答案”。
**
答:
我可能离得很远,但这可能是一个安全问题......我以前遇到过这个错误,我解决了它......但是我花了好几天的时间试图解决许多不同的错误。
我有一篇示例文章做一些基本的事情,但我在这里使用 net.tcp(安全性设置为“无”): 使用 Net.Tcp 在 IIS 中托管的双工 WCF 服务
另外,你从哪里得到错误...是在“.Close()“ 行,或”.GetTasks()。ToString()“行?
您可以检查的另一件事是简单地telnet到端口9999上的localhost,以查看服务是否正在完全侦听传入连接。
确保不会抛出任何不是 FaultException 的内容并将其传递回客户端。
我找到了答案
好的,不确定它是否在回答我自己的问题,但我们开始吧。出于某种原因,枚举需要使用 [EnumMember] 属性进行标记,如下所示:
[DataContract]
public enum Priority
{
[EnumMember]
Low,
[EnumMember]
Medium,
[EnumMember]
High
}
一旦我这样做了,我的测试和服务就可以在不发生错误的情况下被调用。我仍然不确定为什么显示该特定错误。该错误似乎与发生错误的功能原因没有任何相关性,但此修复程序绝对使一切变得平滑。
评论
正如你自己所指出的,如果你将枚举标记为 DataContract,你也必须标记这些项目。
作为替代方案,您可以像这样删除枚举之前的 [DataContract]:
public enum Priority
{
Low,
Medium,
High
}
这也行得通,因为在本例中,WCF 会自行处理枚举。如果你把它标记为[DataContract],你必须像你自己注意到的那样标记每个项目。
有时,此错误可能非常具有误导性。常见的 WCF 异常:当区域性设置不正确或字符串格式设置不正确时,可能会发生连接意外关闭。
以下失败:
new DateTime(adate.Year, adate.Month, firstday).ToString("d", cultureInfo);
虽然这有效:
CultureInfo culture = new CultureInfo(this.aculture.Name);
Convert.ToString(new DateTime(adate.Year, adate.Month, firstday), culture);
我在使用 LINQ 和调用 Select、Where 等时注意到了这一点,而没有立即调用 .ToList() 或 ToArray()。迭代器会给你带来麻烦。它们不是 WCF 知道如何使用的本机类型,如 List、Array 等。它们的类型是 WhereEnumerable 或其他类型。从 NHibernate 或 Entity Framework 发回结果时请记住这一点。希望这对某人有所帮助。我花了几个小时才弄清楚。
评论
我在返回大型有效负载时收到此错误,原来是 DataContractSerialiser 在中途停止,因为它已达到默认的 maxItemsInObjectGraph 设置,将以下内容添加到我的端点行为解决了这个问题
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
此线程上的某个人发布说,将此元素添加到端点行为解决了该问题。
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
这可行,但不仅要添加到端点行为中,还要添加到服务行为中(这是有道理的,因为这是序列化发生的地方)。
如果仅将其添加到服务中,则会出现此错误“对象图中可以序列化或反序列化的最大项目数为'65536'。更改对象图或增加 MaxItemsInObjectGraph 配额。
如果仅添加到端点,我仍然收到连接意外关闭错误。
如果其他人也在这样做,我将返回 linq 生成的对象列表到 sql / dbml 文件。我只需要在dbml文件中启用序列化:
http://blogs.msdn.com/b/wriju/archive/2007/11/27/linq-to-sql-enabling-dbml-file-for-wcf.aspx
干杯
另一个原因:如果你有一个而不是具体类型的属性(可怕的想法,不要这样做),并且你正在尝试序列化 .DataContract/DataMember
Interface
Concrete type
在我的例子中,我返回了一个自定义类对象,其中一个成员是数据表。如果你的数据表上没有名字,它将抛出这个错误。
Dim oTable As DataTable = New DataTable 'this wont serialize
Dim oTable As DataTable = New DataTable("MyTable") 'this will serialize
就我而言,我的数据合约有一个没有设置方法的 [datamember] 属性。我使用 WCF 跟踪来获取真正的错误。https://stackoverflow.com/a/4271528/463425。我希望这对某人有所帮助。
评论