WCF REST Starter Kit Preview の Sample である WebException, WebException2 には、WebProtocolExceptionを使用して例外を処理する方法が説明されています。

WebException は Preview版に含まれる WebErrorHandler ないで処理されることにより、例外の発生したオペレーションのレスポンスフォーマット (WebInvokeAttribute や WebGetAttribute の WebMessageFormat  の値)に従って適切な形式(xml,json)でエラーメッセージをブラウザのレスポンスに設定されるようにしています。

WebException2 はPreview版に含まれる WebErrorHandlerのEnableAspNetCustomErrors を true にすることにより、 WebProtocolException 例外を、ASP.NET の例外処理に統合する方法を説明しています。WebException2では発生した例外をGlobal.asax.csのApplication_EndRequest で例外を補足しています。

  • 動作環境:IIS6.0 on Windows Server 2003
  • 実装確認: Visaul Studio 2008 Professional
  • .NET 3.5 SP1, WCF REST Starter Kit Preview版

1. WebProtocolException

WebExceptionのサンプルは非常にシンプルです。Service.svc.csの抜粋を掲載します。

[ServiceBehavior(IncludeExceptionDetailInFaults = true, InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceContract]
    public partial class Service
    {
.... [WebInvoke(UriTemplate = "DoWork")] [WebHelp(Comment = "This method returns HTTP status code Conflict with a custom XML body")] [OperationContract] SampleResponseBody DoWork(SampleRequestBody request) { throw new WebProtocolException(HttpStatusCode.Conflict, "Custom error data", new SampleErrorBody() { Error = "Sample error" }, null); } [WebInvoke(UriTemplate = "DoWork?json", ResponseFormat = WebMessageFormat.Json)] [WebHelp(Comment="This method returns a HTTP status code Conflict with a custom json error body")] [OperationContract] SampleResponseBody DoWorkJson(SampleRequestBody request) { throw new WebProtocolException(HttpStatusCode.Conflict, "Custom error data in json", new SampleErrorBody() { Error = "Sample error in json" }, null); } }

DoWork オペレーションでは WebInvoke の ResponseFormat が指定されていないので、例外が発した場合は、XML形式でエラーメッセージが返されます。DoWorkJsonは WebInvoke の ResponseFormat が Json のため、Json形式で例外の詳細が返されます。Service には、ほかにもGetData というWebGetAttribute でアノテートされたオペレーションもあります。このメソッドはResponseFormat を指定されていないので、xml形式でエラーメッセージが返されますが、実際はxhtmlのメッセージを返しています。WebProtocolException のどのコンストラクタを使用するかで変わります。詳細は、Preview版の WebProtoclException.cs 内のDataContractDetailWriter クラスと、StringDetailWriter クラスの定義と、コンストラクタでとちらが選択されるかを確認してください。

WebException2では、ASP.NET の例外機構に統合するサンプルです。これは WebException2 サンプルの Service.svc 内で、WebServiceHost2 の EnableAspNetCustomErrors を true にする(結果的にWebErrorHandler.EnableAspNetCustomErrorsがtrueになる)ことで統合できるようにしています。

例外の処理を行っているGlobal.asax.csの抜粋は次のようになっています。サンプルではエラーページにリダイレクトしています。

protected void Application_EndRequest(object sender, EventArgs e)
    {
        if (HttpContext.Current.Error != null)
        {
            WebProtocolException webEx = HttpContext.Current.Error as WebProtocolException;
            if (webEx != null && webEx.StatusCode == HttpStatusCode.BadRequest)
            {
                HttpContext.Current.ClearError();
                HttpContext.Current.Response.Redirect("BadRequest.htm");
            }
        }
    }

2.おまけ

説明は以上です。最後に、こりずに readme.txt を翻訳します。以下はWebExceptionのreadme.txtです。

本サンプルではREST例外に対する例外プログラミングモデルのサポートを説明しています。オペレーションに指定された出力フォーマット(xml もしくは json ) に応じてレスポンセうが返されます。エラーメッセージはシンプルな文字列かもしくはシリアライズ可能なCRL型です。

次にWebException2のreadme.txtの翻訳です。

本サンプルは、WCFのエラー処理機構とASP.NETのカスタム例外機能を統合を説明しています。このサンプルでは、コードはglobal.asaxに追加されており、BadRequst HTTP ステータスコードの場合にカスタムエラーページを表示します。

本サンプルを動かす方法
=====================
ブラウザから、<hostname>/service.svc/GetData?param1=-1 と入力します。param1が負数のため、カスタムエラーページが表示されます。