Общее исключение WCF: соединение неожиданно закрыто
У меня есть три проекта. Один из них - проект служб 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 или в проекте Unit Test с этим кодом:
var client = new TaskManagementClient();
textBox1.Text = client.GetTasks().ToString();
client.Close();
Я получаю следующую ошибку: "Основное соединение было закрыто: соединение было неожиданно закрыто".
Файл app.config для проектов WPF и Unit Test выглядит следующим образом:
<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>
и web.config службы WCF выглядит следующим образом:
<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>
Это не первый случай, когда это произошло, и я предполагаю, что это проблема конфигурации. Но каждый раз, когда я обычно просто сдул свою службу и вернул ее или создал новый сервисный проект. Тогда все работает чудесно. Если у кого-то есть какие-то идеи, это было бы потрясающе. спасибо.
**
Обновлено: я добавил комментарии для более моего устранения неполадок по этой проблеме. Когда ответ будет доступен, если ответ не опубликован, я добавлю его как официальный "ответ".
**
Ответы
Ответ 1
Я нашел ответ
Хорошо, не уверен, что это kewl, отвечая на мой собственный вопрос, но здесь мы идем. По какой-то причине перечисление должно быть помечено атрибутами [EnumMember], как показано ниже:
[DataContract]
public enum Priority
{
[EnumMember]
Low,
[EnumMember]
Medium,
[EnumMember]
High
}
Как только я сделал это, мои тесты и службы можно было бы вызвать без возникновения ошибки. Я все еще не уверен, почему эта конкретная ошибка была отображена. Ошибка, похоже, не выровнена в какой-либо корреляции с функциональной причиной возникновения ошибки, но это исправление определенно сглаживает все.
Ответ 2
Как вы сами отметили, если вы помечаете enum как DataContract, вам также нужно будет пометить элементы.
В качестве альтернативы вы можете просто удалить [DataContract] перед вашим перечислением следующим образом:
public enum Priority
{
Low,
Medium,
High
}
Это тоже сработает, потому что в этом случае WCF обрабатывает перечисление самостоятельно. Если вы отметите его как [DataContract], вы должны отметить каждый элемент, как вы заметили себя.
Ответ 3
Я получал эту ошибку при возврате большой полезной нагрузки, оказалось, что DataContractSerialiser останавливает средний поток, поскольку он попал в настройку maxItemsInObjectGraph по умолчанию, добавив следующее к моему поведению в конечной точке, исправил проблему
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
Ответ 4
Убедитесь, что ничего, что не является FaultException, будет выброшено и передано клиенту.
Ответ 5
Я заметил это при использовании LINQ и вызовов типа Select, Where и т.д. без немедленного вызова .ToList() или ToArray(). Итераторы доставят вам неприятности. Они не являются родными типами, которые WCF знает, как работать с такими как List, Array и т.д. Они имеют тип WhereEnumerable или что-то еще. Просто имейте это в виду при отправке результатов из NHibernate или Entity Framework. Надеюсь, это поможет кому-то. Принял несколько часов, чтобы понять.
Ответ 6
Если кто-то еще это делает, я возвращаю список объектов, которые были сгенерированы файлом linq в sql/dbml. Мне просто нужно включить сериализацию в файле dbml:
http://blogs.msdn.com/b/wriju/archive/2007/11/27/linq-to-sql-enabling-dbml-file-for-wcf.aspx
веселит
Ответ 7
В моем случае мой контракт с данными имел свойство [datamember], у которого не было установленного метода. Я использовал трассировку WCF для получения реальной ошибки. fooobar.com/questions/28415/.... Надеюсь, это поможет кому-то.
Ответ 8
Я мог бы уйти, но это может быть проблема безопасности... Я догадался об этой ошибке, и я решил это... но я был в течение нескольких дней, пытаясь получить много разных ошибок.
У меня есть пример статьи, делающей что-то основное, но я использую net.tcp(с безопасностью, установленной как "Нет" ) здесь: Дуплексные службы WCF Хостинг в IIS с использованием Net.Tcp
Кроме того, где вы получаете ошибку... это в строке ".Close()" или в строке ".GetTasks(). ToString()?
Еще одна вещь, которую вы можете проверить, - просто подключить telnet к localhost на порте 9999, чтобы узнать, слушает ли служба для подключения соединений вообще.
Ответ 9
Иногда эта ошибка может быть очень ошибочной. Общее исключение 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);
Ответ 10
Другая причина: это исключение возникает, если у вас есть DataContract/DataMember
атрибуты на Interface
вместо конкретного типа (ужасная идея, не делайте этого), и вы пытаетесь сериализовать Concrete type
.
Ответ 11
в моем случае я возвращал пользовательский объект класса, одним из членов которого была таблица данных. и если у вас нет имени в datatable, он будет выкидывать эту ошибку.
Dim oTable As DataTable = New DataTable 'this wont serialize
Dim oTable As DataTable = New DataTable("MyTable") 'this will serialize
Ответ 12
Кто-то из этой темы добавил, что добавление этого элемента в поведение конечной точки устранило проблему.
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
Это сработало, но его нужно было добавить не только к поведению конечной точки, но и к поведению службы (что имеет смысл, так как именно здесь будет происходить сериализация).
Если он был добавлен в службу только, я получил эту ошибку: "Максимальное количество элементов, которые могут быть сериализованы или десериализованы в графе объектов, равно" 65536 ". Измените граф объекта или увеличьте квоту MaxItemsInObjectGraph."
Если добавлено только к конечной точке, я все еще получил неожиданно закрытую ошибку соединения.