Common WCF Exception : Connection Unexpectedly Clo

2019-03-15 15:40发布

问题:

I have three projects. One is a WCF Services Project, one is a WPF Project, and one is a Microsoft Unit Testing Project. I setup the WCF Services project with a data object that looks like this:

[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; }
}

My contract looks like this:

[ServiceContract]
public interface ITaskManagement
{
    [OperationContract]
    List<Task> GetTasks();

    [OperationContract]
    void CreateTask(Task taskToCreate);

    [OperationContract]
    void UpdateTask(Task taskToCreate);

    [OperationContract]
    void DeleteTask(Task taskToDelete);
}

When I try to use the service in either the WPF Application or the Unit Test Project with this code:

var client = new TaskManagementClient();

textBox1.Text = client.GetTasks().ToString();

client.Close();

I get the following error: "The underlying connection was closed: The connection was closed unexpectedly."

The app.config for the WPF and Unit Test Projects look like this:

<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>

and the web.config of the WCF Service looks like this:

    <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>

This is not the first time this has happened, and I'm guessing it is a configuration issue. But each time I've usually just blown away my service and put it back or created a new service project. Then everything works wonderfully. If anyone has any ideas, that would be awesome. Thx.

**

Updated: I've added comments for more of my troubleshooting on this problem. When an answer is available, if the answer is unpublished, I'll add it as an official "answer".

**

回答1:

I Found the Answer

Ok, not sure if it is kewl answering my own question, but here we go. For some reason the enumeration needed to be marked with the [EnumMember] Attributes as below:

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

Once I did that my tests and services could be called without the error occurring. I'm still not sure why that specific error was displayed. The error doesn't seem to align in any correlation with the functional reason the error occurred, but this fix definitely smoothed everything out.



回答2:

As you yourself noted, if you mark the enum as DataContract, you'll have to mark the items, too.

As an alternative you could just remove the [DataContract] before your enum like this:

public enum Priority
{    
  Low,    
  Medium,    
  High
}

This would work, too, because in this case WCF handles the enum by itself. If you mark it as [DataContract] you have to mark every item as you noticed yourself.



回答3:

I was getting this error when returning a large payload, it turned out to be the DataContractSerialiser stopping mid stream as it had hit the default maxItemsInObjectGraph setting, adding the folloing to my endpoint behavour fixed the problem

<dataContractSerializer maxItemsInObjectGraph="2147483647" />


回答4:

Make sure that nothing that isn't a FaultException gets thrown and passed back to the client.



回答5:

I've noticed this when using LINQ and calls like Select, Where, etc. without an immediate call to .ToList() or ToArray(). Iterators will get you in trouble. They're not native types that WCF knows how to work with like List, Array, etc. They're of type WhereEnumerable or something. Just keep that in mind when sending back results from NHibernate or Entity Framework. Hope this helps someone. Took me hours to figure out.



回答6:

In case someone else is also doing this, I returning a List of objects that were generated by linq to sql / dbml file. I just had to enable serialization in the dbml file :

http://blogs.msdn.com/b/wriju/archive/2007/11/27/linq-to-sql-enabling-dbml-file-for-wcf.aspx

cheers



回答7:

In my case my data contract had a [datamember] property that did not have a set method. I used a WCF trace to get the real error. https://stackoverflow.com/a/4271528/463425. I hope this helps someone.



回答8:

I could be way off, but it might be a security thing... I've gotten that error before, and I solved it... but I was up for days trying to get a lot of different bugs worked out.

I have a sample article doing something basic, but I'm using net.tcp (with security set to "None") here: Duplex WCF Services Hosted in IIS Using Net.Tcp

Also, where are you getting the error... is it on the ".Close()" line, or the ".GetTasks().ToString()" line?

Another thing you can check is to simply telnet to localhost on port 9999 to see if the service is listening for incomming connections altogether.



回答9:

Sometimes this error could be very misleading. Common WCF Exception : Connection Unexpectedly Closed can be occurred when the culture is not set correctly or in string formating as well.

Following fails:

new DateTime(adate.Year, adate.Month, firstday).ToString("d", cultureInfo);

while this works:

CultureInfo culture = new CultureInfo(this.aculture.Name);               
Convert.ToString(new DateTime(adate.Year, adate.Month, firstday), culture);


回答10:

Another reason: This exception comes up if you have DataContract/DataMember attributes on an Interface instead of a concrete type (terrible idea, don't do it) and you are trying to serialize the Concrete type.



回答11:

in my case i was returning a custom class object, one of the members of which was a data table. and if you dont have a name on the datatable it will throw this error.

Dim oTable As DataTable = New DataTable 'this wont serialize
Dim oTable As DataTable = New DataTable("MyTable")  'this will serialize


回答12:

Someone on this thread posted that adding this element to the endpoint behavior fixed the issue.

<dataContractSerializer maxItemsInObjectGraph="2147483647" />

This worked but it had to be added not only to the endpoint behavior but the service behavior too (which makes sense since that is where the serialization will take place).

If it was added to the service only I got this error "Maximum number of items that can be serialized or deserialized in an object graph is '65536'. Change the object graph or increase the MaxItemsInObjectGraph quota."

If added to the endpoint only I still got the connection unexpectedly closed error.