一般的なWCF例外:接続が予期せず閉じられました
-
04-07-2019 - |
質問
3つのプロジェクトがあります。 1つはWCFサービスプロジェクト、1つはWPFプロジェクト、1つは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();
次のエラーが表示されます:&quot;基礎となる接続が閉じられました:接続が予期せず閉じられました。
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>
これはこれが起こったのは初めてではなく、設定の問題だと思います。しかし、私は通常、自分のサービスを吹き飛ばし、それを元に戻すか、新しいサービスプロジェクトを作成するたびに。その後、すべてがうまく機能します。誰もがアイデアを持っている場合、それは素晴らしいでしょう。 Thx。
**
更新:コメントを追加しました この問題のトラブルシューティングの。 回答が利用可能な場合、 回答は未公開です。追加します 公式の&quot; answer&quot;。
**
解決
答えが見つかりました
はい、それが私自身の質問に答えているのかどうかはわかりませんが、ここに行きます。何らかの理由で、列挙は[EnumMember]属性で次のようにマークする必要がありました。
[DataContract]
public enum Priority
{
[EnumMember]
Low,
[EnumMember]
Medium,
[EnumMember]
High
}
一度テストを行うと、エラーが発生することなくテストとサービスを呼び出すことができます。その特定のエラーが表示された理由はまだわかりません。エラーは、エラーが発生した機能的な理由と相関関係にあるようには見えませんが、この修正によりすべてが完全にスムーズになりました。
他のヒント
ご指摘のとおり、列挙型をDataContractとしてマークする場合は、アイテムもマークする必要があります。
代わりに、次のように列挙の前に[DataContract]を削除することもできます。
public enum Priority
{
Low,
Medium,
High
}
これも機能します。この場合、WCFは列挙型を単独で処理するためです。 [DataContract]としてマークする場合は、すべてのアイテムを自分が気付いたとおりにマークする必要があります。
大きなペイロードを返すときにこのエラーが発生しましたが、デフォルトのmaxItemsInObjectGraph設定に達したためにミッドストリームを停止するDataContractSerialiserであることが判明し、エンドポイントの動作に次の問題が修正されました
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
FaultExceptionではないものがスローされてクライアントに返されないことを確認してください。
.ToList()またはToArray()をすぐに呼び出さずに、LINQを使用してSelect、Whereなどの呼び出しを行うと、このことに気付きました。イテレータはあなたを困らせます。これらは、WCFがList、Arrayなどの操作方法を知っているネイティブ型ではありません。WhereEnumerable型などです。 NHibernateまたはEntity Frameworkから結果を返送するときは、そのことに留意してください。これが誰かを助けることを願っています。理解するのに何時間もかかった。
他の誰かがこれを行っている場合、linqによって生成されたオブジェクトのリストをsql / dbmlファイルに返します。 dbmlファイルでシリアル化を有効にする必要がありました:
http://blogs.msdn.com/b/wriju/archive/2007/11/27/linq-to-sql-enabling-dbml-file-for-wcf.aspx
歓声
私の場合、データコントラクトにはsetメソッドを持たない[datamember]プロパティがありました。 WCFトレースを使用して実際のエラーを取得しました。 https://stackoverflow.com/a/4271528/463425 。これが誰かの助けになることを願っています。
私は大丈夫かもしれませんが、セキュリティ上の問題かもしれません...私は前にそのエラーを取得しました、そしてそれを解決しました... 。
基本的なことを行うサンプル記事がありますが、ここでは<。 .aspx "rel =" nofollow noreferrer "> Net.Tcpを使用してIISでホストされる二重WCFサービス
また、エラーが発生している場所は...&quot; .Close()&quot;行、または&quot; .GetTasks()。ToString()&quot;行?
確認できるもう1つのことは、ポート9999でローカルホストにtelnetで接続し、サービスが完全に着信接続をリッスンしているかどうかを確認することです。
このエラーは非常に誤解を招く場合があります。一般的な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);
別の理由:この例外は、具象型ではなく Interface
に DataContract / DataMember
属性がある場合に発生します(ひどいアイデア、やらないでください) 具象型
をシリアル化しようとしています。
私の場合、カスタムクラスオブジェクトを返していました。そのメンバーの1つはデータテーブルでした。データテーブルに名前がない場合、このエラーがスローされます。
Dim oTable As DataTable = New DataTable 'this wont serialize
Dim oTable As DataTable = New DataTable("MyTable") 'this will serialize
このスレッドの誰かが、この要素をエンドポイントの動作に追加すると問題が解決したと投稿しました。
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
これは機能しましたが、エンドポイントの動作だけでなく、サービスの動作にも追加する必要がありました(シリアル化が行われる場所であるため、これは理にかなっています)。
サービスに追加された場合、このエラーが発生しました&quot;オブジェクトグラフでシリアル化または非シリアル化できるアイテムの最大数は '65536'です。オブジェクトグラフを変更するか、MaxItemsInObjectGraphクォータを増やします。&quot;
エンドポイントのみに追加した場合、接続が予期せず閉じられたというエラーが表示されます。