例外をロギングのために、WCFサービスを利用ELMAH
質問
"を活用し、優れた ELMAH 対応独自のレンダリングメカニズムとモデルにおける例外処理ASP.NET 3.5サポートも組み込まれています。この作品などの全てのサイトのほか、WCFサービスの使用に特徴です。例外発生時の操作方法な取り扱いのアプリケーションコード,WCF取り扱う、さまざまなサービスに応じて契約の設定を設定します。このことは例外となる焼成にASP.NET HttpApplication.エラーイベント ELMAH 利用します。液の知っているしそれに対応するためには:
- 包むすべてのメソッド呼び出しがtry{}catch(Exception ex){Elmah.ErrorSignal.FromCurrentContext().Raise(ex)投;}明示的に呼び出Elmahのcatchブロックです。
- 使用 IErrorHandler に記載のとおり まHughes' ブログ 決WCFとELMAH遊びも一緒に る因子の呼び出ELMAH別のErrorHandler.
最初のオプションは非常にシンプルなものなんですものでない ドライ.第二のオプションのみが必要で飾る各サービスのカスタム属性を実施した後の属性のErrorHandler.そして、これに基づく まー 仕事していきたいと思っていることを検証するこ 正しいアプローチ 前の投稿のコードです。
ありたい?
にMSDN documenation用 IErrorHandler というの HandleError 方法は、ログインが ELMAH アクセスのHttpContext.ます。ApplicationInstance, るがnullの場合このメソッド内でもHttpContext.現在は可能です。を呼び出ElmahのProvideFaultの方法で回避策としてApplicationInstanceはわれていないわけではありませんの意図に記載のAPIドキュメント。 私何かが足りない。 の文書な状態にしないように頼るHandleError法るということは、操作のスレッドがなぜApplicationInstanceがnullの場合この範囲におい
解決
(OPで参照)私のブログの記事からの溶液を、我々は、エラー状態の間にHTTPレスポンスコードを変更するために使用されている/された既存のソリューションに基づいていました。
だから、私たちのためにELMAHに例外を渡すために1行の変化でした。よりよい解決策があれば、私もそれについて知ってみたいです。
後世/参考のために、そして潜在的な改善 - ここでは、現在のソリューションからのコードです。
HttpErrorHandlerとServiceErrorBehaviourAttributeクラス
using System;
using System.ServiceModel;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Collections.ObjectModel;
using System.Net;
using System.Web;
using Elmah;
namespace YourApplication
{
/// <summary>
/// Your handler to actually tell ELMAH about the problem.
/// </summary>
public class HttpErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
return false;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
if (error != null ) // Notify ELMAH of the exception.
{
if (System.Web.HttpContext.Current == null)
return;
Elmah.ErrorSignal.FromCurrentContext().Raise(error);
}
}
}
/// <summary>
/// So we can decorate Services with the [ServiceErrorBehaviour(typeof(HttpErrorHandler))]
/// ...and errors reported to ELMAH
/// </summary>
public class ServiceErrorBehaviourAttribute : Attribute, IServiceBehavior
{
Type errorHandlerType;
public ServiceErrorBehaviourAttribute(Type errorHandlerType)
{
this.errorHandlerType = errorHandlerType;
}
public void Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
{
}
public void AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
{
IErrorHandler errorHandler;
errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
channelDispatcher.ErrorHandlers.Add(errorHandler);
}
}
}
}
使用例
ServiceErrorBehaviour属性を使用してWCFサービスを飾るます:
[ServiceContract(Namespace = "http://example.com/api/v1.0/")]
[ServiceErrorBehaviour(typeof(HttpErrorHandler))]
public class MyServiceService
{
// ...
}
他のヒント
設定を使用して動作をアクティブにすることも可能です。
public class ErrorBehaviorExtensionElement : BehaviorExtensionElement
{
public override Type BehaviorType
{
get { return typeof(ServiceErrorBehaviourAttribute); }
}
protected override object CreateBehavior()
{
return new ServiceErrorBehaviourAttribute(typeof(HttpErrorHandler));
}
}
コンフィグます:
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="elmah" type="Namespace.ErrorBehaviorExtensionElement, YourAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
<behaviors>
<serviceBehaviors>
<behavior>
<elmah />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
その方法には、RIAサービスと組み合わせてELMAHを使用することも可能です!
私はウィルの仕事に基づいてこれを行ってきました しかし、私はこれがあることを確認したいです 投稿する前に、正しいアプローチ コードます。
私は、これは偉大なアプローチだと思う(この投稿のためのウィルへの称賛!)。私はウィルか、ここで何かを見逃しているとは思いません。 IErrorHandlerを実装すると、そうでない場合は、通信チャネルに障害が発生することになり(解体)ので、それはELMAHのようないくつかのログにフックする自然な場所だ可能性のあるすべてのサーバー側の例外をキャプチャする好ましい方法である。
マルク
このはよく、一部の人には自明かもしれないが、私はちょうど私のHttpContext.Currentはウィルヒューズの優れた答えの全てを、以下のにもかかわらず、ヌルた理由を把握しようとかなり長い間を過ごしました。 Embarassingly、私は私のWCFサービスは、MSMQメッセージによって活性化されるので、これがあったことを実現します。
私はProvideFault()
メソッドを書き換えてしまいました
if (HttpContext.Current == null)
{
ErrorLog.GetDefault(null).Log(new Error(error));
}
else
{
ErrorSignal.FromCurrentContext().Raise(error);
}
私は、WCFデータサービスでの作業提案答えを得ることができませんでした。私はなど、行動属性を有線、それでもすべてのエラーが記録されませんでした。代わりに、私はサービスの実装に以下を追加し終わっます:
protected override void HandleException(HandleExceptionArgs args)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(args.Exception);
base.HandleException(args);
}
いったいこの明示的にも、なELMAHのが自分でも十分に検討する価値がフックWCF用 IDispatchMessageInspector の代わりにIErrorHandler.