2012-03-13 16 views
0

例外のために400を返して、私は次のようにErrorHandlerを実装しました:WCFは、常に私はRESTfulなWCFサービスを持っている

public class MyErrorHandler : IErrorHandler, IServiceBehavior 
{ 
    // OMITTED: IServiceBehavior Members 

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
    { 
     DoSomeCustomLogging(error); 
     WebOperationContext ctx = WebOperationContext.Current; 
     ctx.OutgoingResponse.StatusCode = HttpStatusCode.InternalServerError; 
    }   
} 
 
    
public class MyErrorHandlerElement : BehaviorExtensionElement 
{ 
    protected override object CreateBehavior() 
    { 
     return new MyErrorHandler(); 
    } 

    public override Type BehaviorType 
    { 
     get 
     { 
      return typeof(MyErrorHandler); 
     } 
    } 
} 
 

それはそうのように私のweb.configファイルにフックアップしています:

<system.serviceModel> 
    <behaviors> 
    <endpointBehaviors> 
     <behavior name="Rest"> 
     <webHttp /> 
     </behavior> 
    </endpointBehaviors> 
    </behaviors> 
    <extensions> 
    <behaviorExtensions> 
     <add name ="errorHandler" type="ACME.MyErrorHandlerElement, ACME.MyErrorHandler"/> 
    </behaviorExtensions> 
    </extensions> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> 
    <standardEndpoints> 
    <webHttpEndpoint> 
     <standardEndpoint name="" faultExceptionEnabled="false" helpEnabled="false"  automaticFormatSelectionEnabled="true" /> 
    </webHttpEndpoint> 
    </standardEndpoints> 
</system.serviceModel> 

何らかの理由で、サービスが例外をスローすると、500ではなくクライアントに400が返されます。理由は何ですか?

+0

webconfigがありません。 –

+0

を設定ファイルで更新してください。MyErrorHandlerElement - MyErrorHandlerにする必要がありますか? – Eric

+0

Ericの場合、最初の項目はErrorHandlerElementです(これを含めるために私のサンプルが更新されています)。2番目の要素はアセンブリ名です。 – Bullines

答えて

1

参照によって渡されるフォールトを変更する必要があります。これは通常のWebメソッド呼び出しではありません。

#Region "IErrorHandler Members" 
Public Function HandleError(ByVal [error] As Exception) As Boolean Implements IErrorHandler.HandleError 
    Console.WriteLine("HandleError called.") 
    ' Returning true indicates you performed your behavior. 
    Return True 
End Function 

' This is a trivial implementation that converts Exception to FaultException<GreetingFault>. 
Public Sub ProvideFault(ByVal [error] As Exception, ByVal ver As MessageVersion, ByRef msg As Message) Implements IErrorHandler.ProvideFault 
    Console.WriteLine("ProvideFault called. Converting Exception to GreetingFault....") 
    Dim fe As New FaultException(Of GreetingFault)(New GreetingFault([error].Message)) 
    Dim fault As MessageFault = fe.CreateMessageFault() 
    msg = Message.CreateMessage(ver, fault, "http://microsoft.wcf.documentation/ISampleService/SampleMethodGreetingFaultFault") 
End Sub 
#End Region 

MSDN Source

+0

これを実装するには、サービスメソッドによって呼び出されるビジネスコンポーネントに例外がスローされたときに200が返されるようになりました。どちらも理想的ではありません。ただし、サービスメソッド自体によって例外がスローされた場合は、これは正常です(500を返します)。 – Bullines

0

良いニュースと悪いニュースがあります。良いことは、あなたの設定が正しくていれば、あなたのコードがうまくいくということです。私はすぐに修正を提供します。悪い知らせは、この解決法は安定していない可能性があるということです。 MSDNのドキュメントによると、ProvidFault method is not guaranteed to execute on the same thread as the service operationと同様にWebOperationContext.Currentのようなものにアクセスするとヒットミスになる可能性があります。ここでは、言った

あなたは、固定得るものである。

設定が間違っているので、あなたは、あなたが期待する結果が表示されません。あなたの設定では拡張機能が正しく宣言されていますが、エンドポイントで使用する必要があることを宣言しても構いません。あなたが持つかもしれない

<system.serviceModel> 
    <!-- ****************** --> 
    <behaviors> 
    <serviceBehaviors> 
     <behavior> 
     <errorHandler /> 
     </behavior> 
    </serviceBehaviors> 
    </behaviors> 
    <!-- ****************** --> 
    <extensions> 
    <behaviorExtensions> 
     <add name ="errorHandler" type="ACME.MyErrorHandlerElement, ACME.MyErrorHandler"/> 
    </behaviorExtensions> 
    </extensions> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> 
    <standardEndpoints> 
    <webHttpEndpoint> 
     <standardEndpoint name="" faultExceptionEnabled="false" helpEnabled="false"  automaticFormatSelectionEnabled="true" /> 
    </webHttpEndpoint> 
    </standardEndpoints> 
</system.serviceModel> 

もう一つの問題は、あなたの設定が有効にasp.net互換モードを持っていることである2つのアスタリスクのコメントの間に、私はあなたの設定に挿入修正があります。このモードが有効になっていると、インストールされている動作に問題があります。あなたのマイレージは異なる場合があります。

最後にもう一つの事、あなたのアプローチを継続したいMSDNのドキュメントからの警告にもかかわらず、その後、私はあなたがあなたのIErrorHandler拡張表情を作る提案する場合は、このような何か:

public void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
{ 
    var faultEx = error as FaultException; 
    bool isRest = version == MessageVersion.None; 

    if (isRest && faultEx == null) 
    { 
     OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse; 
     if (response.StatusCode == HttpStatusCode.BadRequest) { 
      response.StatusCode = HttpStatusCode.InternalServerError; 
     } 
    } 
} 

上記のコードは、あなたのドンことを保証しますサービスオペレーション開発者によって明示的に設定されたステータスコードを誤って上書きすることはありません。また、開発者がスローしたWebFaultExceptionエラーは、開発者が割り当てたステータスコードで伝播することもできます。

関連する問題