通信オブジェクトSystem.ServiceModel.Channels.ServiceChannelは、障害状態にあるため、通信に使用できません。
このエラーとは何ですか?どのように解決しますか?
このエラーが発生するのは、サーバー側で.NET例外が発生し、キャッチも処理もされず、SOAPフォールトにも変換されなかったためです。
サーバー側が「爆撃」されたので、WCFランタイムはチャネルを「フォールト」しました。クライアントとサーバー間の通信リンクは使用できません-結局、サーバーが爆発したように見えるため、それ以上通信できなくなります。
だからあなたがする必要があるのは:
alwaysサーバー側のエラーをキャッチして処理する-do notlet。 NET例外はサーバーからクライアントに移動します-alwaysは、それらを相互運用可能なSOAPフォールトにラップします。 WCF IErrorHandler インターフェイスをチェックアウトし、サーバー側に実装します
クライアントからチャンネルに2番目のメッセージを送信する場合は、チャンネルが障害状態になっていないことを確認してください。
if(client.InnerChannel.State != System.ServiceModel.CommunicationState.Faulted)
{
// call service - everything's fine
}
else
{
// channel faulted - re-create your client and then try again
}
そうである場合、できることはそれを破棄し、クライアント側プロキシを再作成してから再試行することだけです
サーバーがフォールト状態に陥らないようにするには、未処理の例外が発生しないようにする必要があります。 WCFが予期しない例外を検出した場合、それ以上の呼び出しは受け付けられません-安全第一。
この動作を回避するための2つの可能性:
FaultExceptionを使用します(これはWCFにとって予期しないことではないため、WCFはサーバーがまだ有効な状態であることを認識しています)
の代わりに
throw new Exception("Error xy in my function")
常に使用する
throw new FaultException("Error xy in my function")
おそらく、ブロック全体をキャッチして、例外のすべての場合にFaultExceptionをスローできます
try
{
... some code here
}
catch (Exception ex)
{
throw new FaultException(ex.Message)
}
Errorhandlerを使用してすべての例外を処理するようにWCFに指示します。これはいくつかの方法で実行できますが、属性を使用して簡単な方法を選択しました。
さらに行う必要があるのは、必要なサービス実装で属性[SvcErrorHandlerBehaviour]
を使用することだけです
using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace MainService.Services
{
/// <summary>
/// Provides FaultExceptions for all Methods Calls of a Service that fails with an Exception
/// </summary>
public class SvcErrorHandlerBehaviourAttribute : Attribute, IServiceBehavior
{
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{ } //implementation not needed
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints,
BindingParameterCollection bindingParameters)
{ } //implementation not needed
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcherBase chanDispBase in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = chanDispBase as ChannelDispatcher;
if (channelDispatcher == null)
continue;
channelDispatcher.ErrorHandlers.Add(new SvcErrorHandler());
}
}
}
public class SvcErrorHandler: IErrorHandler
{
public bool HandleError(Exception error)
{
//You can log th message if you want.
return true;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
{
if (error is FaultException)
return;
FaultException faultException = new FaultException(error.Message);
MessageFault messageFault = faultException.CreateMessageFault();
msg = Message.CreateMessage(version, messageFault, faultException.Action);
}
}
}
これは簡単な例です。裸のFaultException
を使用せずにIErrorhandlerを深く掘り下げることができますが、追加情報を提供する型のFaultException<>
を使用して、詳細な例については IErrorHandler を参照してください。
実際のところ、次の提案に従って失敗した場合 marc_s、サーバーのweb.configのサーバーバインディング構成(またはその欠如)の<security>要素がこの例外を引き起こす可能性があることに注意してください。たとえば、サーバーはMessage
レベルのセキュリティを期待しており、クライアントはNone
に構成されています(または、サーバーがActive Directoryドメインの一部ではなく、リモートクライアントホストの場合)。
ヒント:このような場合、RDPセッションの管理者アカウントでサーバーマシンで直接実行すると、クライアントアプリはほとんどの場合、Webサービスを正常に呼び出します。
faulted
イベント に接続して、エラーが発生した理由とタイミングを把握します。
編集:あなたがやっていることについてのいくつかの情報を投稿した場合にも役立ちます。
この問題を診断するには、Visual Studioデバッガーでサービスを実行します。メニューDebug | Exceptionsを使用して、例外がスローされたときに中断することを示します。
スローされた元の例外のエラーメッセージは、「.. itがFaulted状態です」よりもはるかに優れています。
たとえば、ServiceHost.Open()からこの例外を取得していましたが、スローされたときに元の例外をキャッチすると、エラーメッセージは次のようになりました。
サービス 'MyServiceName'には、アプリケーション(非インフラストラクチャ)エンドポイントがありません。これは、アプリケーションの構成ファイルが見つからなかったか、構成ファイルにサービス名に一致するサービス要素が見つからなかったか、サービス要素にエンドポイントが定義されていなかったためです。
App.configのスペルエラーを修正して、問題を解決しました。
WCFを介してWindowsサービスに接続するWebクライアントがあります。私のウェブアプリは同じエラーを投げます
通信オブジェクトSystem.ServiceModel.Channels.ServiceChannelは、障害状態にあるため、通信に使用できません WCFトレースを有効にしましたが、あまり役に立ちませんでした。最後にWindowsサービスを再起動すると解決しましたが、原因はまだわかりません。そのため、トラブルシューティングはいつものように単純なものから始める必要があります。これは適切な例です。誰かが同様の問題を抱えている場合は、サービスを再起動してください。
私は別の問題を抱えていました。他の答えで言及されていなかったと思います。
同じtcpアドレスとポートでエンドポイントをサービスする必要があります。 app.configで、両方のエンドポイントを追加するのを忘れていたため、サービスは正しいポートで実行されていましたが、サービスインターフェイスが間違っていました。
Http asmxサービスでnet.tcp wcfサービスエンドポイントを使用しようとしたときに同じ問題が発生しました。
私が見たように、誰も具体的な答えを書いていないのはなぜこの問題が発生しているのか、しかし適切に処理される方法だけです。
私は数日間続けてそれに苦労してきましたが、最終的に私の問題の原因がどこにあるかを見つけました。
最初に、サービスへの参照を作成するときに、ソース内と同じ方法でセキュリティタグに関して設定ファイルが設定されると考えましたが、そうではなく、手動で処理する必要があります。私の場合は
<netTcpBinding>
<binding name="NetTcpBinding_IAuthenticationLoggerService"
</binding>
</netTcpBinding>`
後で、セキュリティ部分が欠落していることがわかりました。これは次のようになります。
<netTcpBinding>
<binding name="NetTcpBinding_IAuthenticationLoggerService" transferMode="Buffered">
<security mode="None">
<transport clientCredentialType="None"/>
</security>
</binding>
</netTcpBinding>
私の場合の2番目の問題は、ソースのWCFサービスでtransferMode="Streamed"
を使用しており、クライアントでは特定の情報が何もなかったことでした。デフォルトのtransferMode
はBuffered
そして、ソースとクライアントの両方の場所で同じように構成することが重要です。
Visual Studioからのデバッグでこのメッセージが表示され、ソリューションにWCFプロジェクトが含まれている場合。次に、このWCFプロジェクト設定を開きます-> [WCFオプション]タブに移動-> [デバッグ時にWCFサービスホストを開始...]オプションをオフにします
私にとっては、ロードバランサー/ URLの問題でした。ロードバランサーの背後にあるWebサービスは、次のような完全なURLを使用して、同じロードバランサーの背後にある別のサービスを呼び出しました:loadbalancer.mycompany.com
。代わりにlocalhost.mycompany.com
を使用して、2番目のサービスを呼び出すときにロードバランサーをバイパスするように変更しました。
ロードバランサーで何らかの循環参照の問題が発生したと思います。
私の場合、理由はロードできなかった証明書が間違っていたためです。 Systemの下のEvent Viewerからそれを見つけました。
TLSサーバーの秘密鍵にアクセスしようとしたときに致命的なエラーが発生しました。暗号化モジュールから返されるエラーコードは0x8009030Dです。内部エラー状態は10001です。
このエラーは、未処理の例外だけでなく、ご使用のコンピューターでもトリガーできます。サーバー/コンピューターの時計の時間があまりにも長い場合、多くの.NET Webサービスは未処理のエラーでリクエストを拒否します。それらの観点からは処理されますが、あなたの観点からは処理されません。受信サーバーの時刻が正しいことを確認してください。修正が必要な場合は、チャンネルを再開する前にサービスをリセットするか再起動する必要があります。
ファイアウォールがインターネット時刻の更新をブロックしたサーバーでこの問題が発生し、何らかの理由でサーバーが時間切れになりました。サードパーティの.NET Webサービスはすべて、Webサービス要求を拒否したために障害が発生しました。イベントビューアを掘り下げて問題を特定することはできましたが、クロックを調整することで解決しました。将来のWebサービス呼び出しでFaulted Stateエラーメッセージを受信した場合でも、エラーは終わりです。
これは古い投稿ですが、セキュリティを変更できない場合に注意する必要があるのは、ユーザー名とパスワードが設定されていることを確認することです。
ユーザー名とパスワードがサービスクライアントに設定されていない場合、このエラーが発生します。
サーバーは、受信タイムアウト(デフォルトは10分)に等しい期間メッセージを受信しなかった接続を自動的に中止します。これは、クライアントが無期限にサーバーに接続を開かせることを防ぐDoS緩和策です。
サーバーは接続がアイドル状態になったために接続を中止するため、クライアントはこの例外を受け取ります。
サーバーのバインディングで受信タイムアウトを構成することで、サーバーが接続を中断する前にアイドル状態にする時間を制御できます。クレジット:T.R. Vishwanath-MSFT