ASP.NETの例外の処理について
※事前に 例外処理の基本 の理解が必要です。
例外をキャッチして適切に処理する
HttpApplicationクラスのApplication_Errorメソッド
ASP.NETでは未処理例外の管理をするためのいくつかの方法があります。 .aspxや.ashxなどの拡張子へのアクセスに対してはHttpApplicationを継承するGloablクラスのApplication_Errorメソッドに 処理を記述することによって例外時の処理を実行できます。
            protected void Application_Error(object sender, EventArgs e)
            {
                Exception ex = Server.GetLastError();
                //例外が発生したときの処理を記述。
                //例外をログに記録するなど…
            }
非常に簡単です。
WCFのエラーをまとめて処理するには?
拡張子が.svcで終わるWCFサービスの場合はApplication_Errorメソッドではキャッチできません。 WCFでは全ての例外はキャッチされ、HTTP通信としては200の正常終了として扱われるためです。 例外が発生した場合は例外情報を文字列としてエラーコードと共にクライアントに送信するようになっています。 その結果としてApplication_Errorの呼び出しはされません。
WCFサービス内で発生した例外をまとめて扱う仕組みは別途用意されています。方法を解説しますが上記のApplication_Error メソッドに比べると少し複雑です。手順としては といった形になります。まずはMyWcfServiceErrorHandlerクラスを作成しましょう。
            public class MyWcfServiceErrorHandler : IErrorHandler
            {
                public bool HandleError(Exception error)
                {
                    if (error is FaultException)
                    {
                        // ここにログ出力処理を書く
                    }
                    return false;
                }
                public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
                {
                    //このメソッドの中でクライアントに送信するエラーメッセージの編集が可能です。
                    //引数で渡されてくるfault変数にMessageオブジェクトを作成してセットします。
                    var reasonTexts = new FaultReasonText[] { new FaultReasonText("???のエラーが発生しました。") };
                    fault = this.CreateErrorMessage(version, reasonTexts);
                }
                private Message CreateErrorMessage(MessageVersion version, FaultReasonText[] reasonTexts)
                {
                    FaultReason reason = new FaultReason(reasonTexts);
                    FaultCode code = FaultCode.CreateReceiverFaultCode("unexpected", "");
                    FaultException faultException = new FaultException(reason, code);
                    MessageFault messageFault = faultException.CreateMessageFault();
                    String action = OperationContext.Current.IncomingMessageHeaders.Action;
                    return Message.CreateMessage(version, messageFault, action);
                }
            }
次にMyWcfServiceErrorAttributeクラスを作成します。
            [AttributeUsage(AttributeTargets.Class)]
            public class MyWcfServiceErrorAttribute : Attribute, IServiceBehavior
            {
                private IErrorHandler errorHandler;
                public WebServiceErrorHandlerAttribute()
                {
                    this.errorHandler = new MyWcfServiceErrorHandler();
                }
                public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase
                    , Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
                {
                }
                public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
                {
                    foreach (ChannelDispatcherBase dispatcherBase in serviceHostBase.ChannelDispatchers)
                    {
                        ChannelDispatcher dispatcher = dispatcherBase as ChannelDispatcher;
                        if (dispatcher == null)
                        {
                            continue;
                        }
                        dispatcher.ErrorHandlers.Add(this.errorHandler);
                    }
                }
                public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
                {
                }
            }
作成した属性をWCFサービスのクラスにセットします。
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
[MyWcfServiceError]
public class WcfApiService
{
    [OperationContract]
    public String GetUserInfo(String parameter)
    {
    }
}
属性を付与したクラスのメソッド内で例外が発生した場合、属性クラス内で指定したハンドラーが実行されるようになります。 このような仕組みになっているので例えばWCFのサービスクラスごとに異なる例外処理を行うようにすることも可能です。
Create at 2013/4/05 LastUpdate 2013/4/05