回答:
このエラーが発生するのは、サーバー側で.NET例外を発生させ、それをキャッチして処理せず、SOAPフォールトに変換しなかったためです。
サーバー側が「爆撃」されたため、WCFランタイムがチャネルに「障害」を起こしました。たとえば、クライアントとサーバー間の通信リンクが使用できなくなります-結局のところ、サーバーが故障したように見えるため、通信できませんそれ以上。
だからあなたがする必要があるのは:
常にサーバー側のエラーをキャッチして処理します。.NETの例外がサーバーからクライアントに伝わらないようにしてください。それらは常に相互運用可能な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);
}
}
}
これは簡単な例です。nakedを使用せずにIErrorhandlerをさらに詳しく調べることができますFaultException
が、FaultException<>
追加情報を提供する型を使用して、詳細な例についてIErrorHandlerを参照してください。
実際のところ、marc_sの提案に従っても失敗した場合、サーバーのweb.configのサーバーバインディング構成の<security>要素(またはその欠如)がこの例外を引き起こす可能性があることに注意してください。たとえば、サーバーは- Message
レベルのセキュリティを想定しており、クライアントはに設定されていますNone
(または、サーバーがActive Directoryドメインの一部ではなく、リモートクライアントホストの一部である場合)。
ヒント:このような場合、RDPセッションの管理者アカウントでサーバーマシン上で直接実行すると、クライアントアプリがWebサービスを正常に呼び出す可能性があります。
この問題を診断するには、Visual Studioデバッガーでサービスを実行します。[デバッグ|例外]メニューを使用して、例外がスローされたときに中断することを指定します。
スローされた元の例外には、「..障害状態です」よりもはるかに優れたエラーメッセージが表示されます。
たとえば、ServiceHost.Open()からこの例外を取得していましたが、スローされたときに元の例外をキャッチすると、エラーメッセージは次のようになりました。
サービス「MyServiceName」には、アプリケーション(インフラストラクチャでない)エンドポイントがありません。これは、アプリケーションの構成ファイルが見つからなかったか、構成ファイルでサービス名と一致するサービス要素が見つからなかったか、サービス要素でエンドポイントが定義されていなかったことが原因である可能性があります。
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番目の問題は、transferMode="Streamed"
ソースWCFサービスで使用していて、クライアントでは何も特定していなかったということです。これは、デフォルトでtransferMode
ありBuffered
、ソースとクライアントの両方で同じように構成することが重要であるためです。仕方。
Visual Studioからのデバッグでこのメッセージが表示され、ソリューションにWCFプロジェクトが含まれている場合。次に、このWCFプロジェクト設定を開きます-> [WCFオプション]タブに移動します-> [デバッグ時にWCFサービスホストを開始...]オプションをオフにします
私にとっての問題は、WSDLのインポートによって自動的に生成された構成ファイルが原因でした。バインディングをbasicHttpBindingからcustomBindingに更新しました。例外処理を追加しても、これを指摘するのに役立ちませんでした。
前
<basicHttpBinding>
<binding name="ServiceName">
<security mode="Transport" />
</binding>
</basicHttpBinding>`
後
<customBinding>
<binding name="ServiceName">
<textMessageEncoding messageVersion="Soap12" />
<httpsTransport />
</binding>
</customBinding>`
このエラーは、ハンドルされていない例外だけでなく、ご使用のコンピューターによってもトリガーされます。サーバー/コンピューターのクロックタイムが長すぎると、多くの.NET Webサービスが未処理のエラーでリクエストを拒否します。彼らの観点からは処理されますが、あなたの観点からは処理されません。受信サーバーの時刻が正しいことを確認してください。修正する必要がある場合は、サービスをリセットするか、チャネルを再開する前に再起動する必要があります。
ファイアウォールがインターネット時刻の更新をブロックしているサーバーでこの問題が発生し、サーバーが何らかの理由でオフタイムになりました。すべてのサードパーティの.NET Webサービスは、Webサービス要求を拒否したため、障害が発生しました。イベントビューアを掘り下げることで問題を特定することができましたが、クロックを調整することで解決しました。エラーは、将来のWebサービス呼び出しのためにFaulted Stateエラーメッセージを受信したにもかかわらず、私たちの側にありました。
私にとっては、ロードバランサー/ URLの問題でした。ロードバランサーの背後にあるWebサービスが、次のような完全なURLを使用して同じロードバランサーの背後にある別のサービスを呼び出しましたloadbalancer.mycompany.com
。localhost.mycompany.com
代わりにを使用して2番目のサービスを呼び出すときに、ロードバランサーをバイパスするように変更しました。
ロードバランサーで何らかの循環参照の問題が発生していたと思います。
この問題の解決策ではありませんが、Ektron eSyncで上記のエラーが発生する場合は、データベースのディスク領域が不足している可能性があります。
編集:実際、これは完全にEktron eSyncのみの問題ではありません。これは、データベース全体を照会するサービスで発生する可能性があります。
編集:ディスク容量不足、または必要なディレクトリへのアクセスをブロックすると、この問題が発生します。