У меня три проекта. Один - это проект служб 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();
Я получаю следующую ошибку: «Базовое соединение было закрыто: соединение было неожиданно закрыто».
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>
Это не первый раз, и я предполагаю, что это проблема конфигурации. Но каждый раз я обычно просто сдуваю свой сервис и кладу его обратно или создаю новый сервисный проект. Тогда все работает замечательно. Если у кого-то есть идеи, это было бы здорово. Спасибо.
**
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".
**





Я мог быть далеко, но это могло быть связано с безопасностью ... Я получал эту ошибку раньше, и я решил ее ... но я несколько дней пытался исправить множество разных ошибок.
У меня есть образец статьи, посвященной чему-то базовому, но я использую net.tcp (с настройкой безопасности "None") здесь: Дуплексные службы WCF, размещенные в IIS с использованием Net.Tcp
Кроме того, где вы получаете ошибку ... в строке ".Close ()" или в строке ".GetTasks (). ToString ()"?
Еще одна вещь, которую вы можете проверить, - просто подключиться к локальному хосту через порт 9999 через Telnet, чтобы узнать, прослушивает ли служба все входящие соединения.
Убедитесь, что ничего, кроме FaultException, не генерируется и не передается обратно клиенту.
Я нашел ответ
Хорошо, не уверен, отвечает ли он на мой собственный вопрос, но поехали. По какой-то причине перечисление нужно было пометить атрибутами [EnumMember], как показано ниже:
[DataContract]
public enum Priority
{
[EnumMember]
Low,
[EnumMember]
Medium,
[EnumMember]
High
}
Как только я это сделал, мои тесты и сервисы можно было вызывать без возникновения ошибки. Я до сих пор не понимаю, почему была отображена именно эта ошибка. Ошибка, похоже, не соответствует какой-либо корреляции с функциональной причиной возникновения ошибки, но это исправление определенно сгладило все.
хорошо отвечать на свой вопрос: meta.stackexchange.com/questions/17463/… - думаю, для этого должен быть значок! :)
Я думал, что этот ответ был немного случайным. Но полностью раскрыл мой случай!
Как вы сами заметили, если вы отметите перечисление как 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. Надеюсь, это кому-то поможет. Мне потребовались часы, чтобы понять.
Верно. Вы можете вернуть IEnumerable <T> и уйти с ленивым вычислением, но если вы вернете тип, который имеет экземпляр IEnumrable <T>, тогда вам лучше вызвать ToList () или иначе. Итак, yield 1; выход 2; выход 3; будет работать, но новый TopLevelObject {Values = некоторая ленивая вычисляемая последовательность} поможет вам.
Я получал эту ошибку при возврате большой полезной нагрузки, оказалось, что 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-enables-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], у которого не было метода set. Я использовал трассировку WCF, чтобы получить настоящую ошибку. https://stackoverflow.com/a/4271528/463425. Я надеюсь, что это помогает кому-то.
Из всех случайных исключений, которые кто-то мог выдать, это САМОЕ ЛУЧШЕЕ, что могла придумать команда WCF? Я столкнулся с той же проблемой, и я потратил вечность, пытаясь понять, и, чтобы сделать это еще более раздражающим, он работал на моей тестовой машине, но не работал должным образом при перемещении на сервер. IIS - это зло.