常见WCF异常:连接意外关闭

12

我有三个项目。一个是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>

这已经不是第一次发生了,我猜测这是一个配置问题。但每次通常都只是删除我的服务并重新创建或者创建一个新的服务项目。然后一切都很完美。如果有人有任何想法,那就太棒了。谢谢。

**

更新:我已经添加了更多的排除故障信息。当有答案可用时,如果答案未发布,我将把它作为官方“答案”添加。

**

12个回答

21

我找到了答案

好的,不确定自己回答自己的问题是否好,但我们开始吧。由于某种原因,需要使用以下方式标记枚举值 [EnumMember] Attributes:

[DataContract]
public enum Priority
{
    [EnumMember]
    Low,
    [EnumMember]
    Medium,
    [EnumMember]
    High
}

我这样做之后,我的测试和服务都可以被调用而不会出现错误。我仍然不确定为什么会显示那个具体的错误。这个错误似乎与错误发生的功能原因没有任何相关性,但这个修复确实使一切变得更加顺畅。


2
在所有可能抛出的随机异常中,WCF团队能想到的就是这个最好的吗?我也遇到了完全相同的问题,花费了很长时间才试图解决它,更令人恼火的是,在我的测试机器上它可以工作,但当移动到服务器上时却无法正常工作。IIS太邪恶了。 - thaBadDawg
回答自己的问题也是可以的:http://meta.stackexchange.com/questions/17463/can-i-answer-my-own-questions-even-those-where-i-knew-the-answer-before-asking - 我认为应该有一个徽章来表彰这种行为! :) - russau
我觉得这个答案有点随意,但完全解决了我的问题! - E-A

7

正如您自己所指出的,如果您将枚举标记为DataContract,则还必须标记项目。

作为替代方案,您可以只是删除枚举前面的[DataContract],像这样:

public enum Priority
{    
  Low,    
  Medium,    
  High
}

这也可以运行,因为在这种情况下,WCF会自己处理枚举。如果你将其标记为[DataContract],你必须像你自己注意到的那样标记每个项。

6

当返回大量负载时,我遇到了这个错误,原来是由于DataContractSerialiser在流中间停止了,因为它已经达到了默认的maxItemsInObjectGraph设置。将以下内容添加到我的端点行为中可以解决问题。

<dataContractSerializer maxItemsInObjectGraph="2147483647" />

3

我注意到,在使用LINQ时,如果没有立即调用.ToList()或.ToArray()等方法,会出现问题。迭代器会给你带来麻烦。它们不是WCF知道如何处理的原生类型,如List、Array等。它们属于WhereEnumerable类型或其他类型。因此,请在从NHibernate或Entity Framework返回结果时记住这一点。希望这能帮助到某些人。我花了几个小时才弄明白。


确实。你可以返回IEnumerable<T>并使用延迟计算,但如果你返回一个具有IEnumrable<T>实例的类型,那么最好调用ToList(),否则会出问题。所以yield 1; yield 2; yield 3;是可以工作的,但new TopLevelObject { Values = some lazy evaluated sequence }就会出问题。 - A-Dubb

3

确保不会抛出任何不是FaultException的异常并传回客户端。


2

2

1
有时候这个错误可能会非常误导人。常见的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);

1

我可能完全错了,但这可能是一个安全问题... 我以前也遇到过这个错误,我解决了它... 但我花了几天时间来解决很多不同的错误。

我有一个样例文章做一些基本的事情,但我在这里使用 net.tcp(安全设置为“无”):Duplex WCF Services Hosted in IIS Using Net.Tcp

另外,你在哪里得到这个错误... 是在“.Close()”行还是“.GetTasks().ToString()”行?

另一件事情是你可以检查一下,只需telnet到本地主机的9999端口,看看服务是否完全监听传入连接。


1
另一个原因:如果您在接口上使用了DataContract/DataMember属性而不是具体类型(糟糕的想法,不要这样做),并且您正在尝试序列化具体类型,则会出现此异常。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接