2012-05-23 123 views
4

摘要:WCF REST錯誤處理 - 錯誤輸入

在WCF REST服務如何使用自己的定製故障響應我處理不正確的輸入參數?

詳細信息:

我有一個WCF REST服務下面的接口方法:

[OperationContract] 
[WebGet(UriTemplate = "getitem?id={itemId}", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)] 
[FaultContract(typeof(DataModel.Fault))] 
DataModel.Item GetItem(int itemId); 

在我執行的GetItem方法我發現任何錯誤條件(即項目不存在)並創建一個WebFaultException。這工作沒有任何問題。

但是,可以說,調用客戶端調用下面的網址:

http://myserver.com/itemservice/getitem?id=abc

即對於ID輸入值不能轉換成int所要求的的GetItem方法

此調用正確失敗因爲給定的id值不能轉換爲int,但是這個失敗發生在我的任何代碼被執行之前,因此我無法按照分配給接口方法的FaultContract返回我的DataModel.Fault對象。

所以,問題是,我怎麼可以掛鉤一個高級別的錯誤處理程序來捕獲這種類型的錯誤,隨後回到我自己的錯結構,而不是HTML錯誤WCF生成:

請求錯誤 的服務器在處理請求時遇到錯誤。查看服務器日誌獲取更多詳細信

由於同樣的問題,我也想能夠做同樣的事情的延續,如果客戶要求如下:

http://myserver.com/itemservice/gettitem?id=abc

通知URI中的錯字,gettitem(兩個t)而不是getitem

回答

1

使用IErrorHandler接口來擴展您的服務。

這將允許您爲任何異常提供適當的錯誤。 This post顯示瞭如何將自己的錯誤處理程序連接到您的服務行爲。

我個人使用一個類來實現這樣所有必要的元素:

public class ErrorSavingServiceBahavior : BehaviorExtensionElement, IServiceBehavior, IErrorHandler 
{ 
    private string m_sHostName; 

    public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) 
    { 
    } 

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) 
    { 
     this.m_sHostName = serviceHostBase.Description.Name; 
     foreach (ChannelDispatcher chanDisp in serviceHostBase.ChannelDispatchers) 
     { 
      if (!chanDisp.ErrorHandlers.Contains(this)) 
      { 
       chanDisp.ErrorHandlers.Add(this); 
      } 
     } 
    } 

    public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) 
    { 
    } 

    public bool HandleError(Exception error) 
    { 
     //my custom code 
    } 

    public void ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault) 
    { 
     //my custom code 
    } 

    public override Type BehaviorType 
    { 
     get { return this.GetType(); } 
    } 

    protected override object CreateBehavior() 
    { 
     return this; 
    } 
} 

和web.config中我與擴展:

<behaviors> 
    <serviceBehaviors> 
    <behavior name="BehaviorName"> 
     <serviceMetadata httpGetEnabled="true"/> 
     <serviceDebug includeExceptionDetailInFaults="true" httpHelpPageEnabled="true"/> 
     <saveExceptions /> 
    </behavior> 
    </serviceBehaviors> 
</behaviors> 
<extensions> 
    <behaviorExtensions> 
    <add 
     name="saveExceptions" 
     type="Namespace.Class, DLLName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" 
    /> 
    </behaviorExtensions> 
</extensions>