2014-04-24 42 views
1

我想在使用iis和net.tcp的WCF服務中實現IErrorHandler。WCF FaultException IErrorHandler - 沒有返回到客戶端,導致超時異常

我設置了在服務器中拋出DivideByZeroException的場景。 IErrorHandler按預期發射。

FaultException不返回到客戶端,我得到超時異常。我在事件日誌中也找不到任何信息/異常。

這裏是演示代碼。 http://www.fileswap.com/dl/gQFlVsZK7M/(由檔案添加的代碼都可以看到它)(請點擊下載慢圖像)

編輯1:

服務合同:

[ServiceContract] 
public interface IService1 
{ 

    [OperationContract] 
    [FaultContract(typeof(DivideByZeroException))] 
    string GetData(int value); 

    [OperationContract] 
    [FaultContract(typeof(DivideByZeroException))] 
    CompositeType GetDataUsingDataContract(CompositeType composite); 

    // TODO: Add your service operations here 
} 

服務實現:

public class Service1 : IService1 
{ 
    public string GetData(int value) 
    { 
     int i = 0; 

     //division by zero! 
     int y = 10/i; 
     return string.Format("You entered: {0}", value); 
    } 

    public CompositeType GetDataUsingDataContract(CompositeType composite) 
    { 
     if (composite == null) 
     { 
      throw new ArgumentNullException("composite"); 
     } 
     if (composite.BoolValue) 
     { 
      composite.StringValue += "Suffix"; 
     } 
     return composite; 
    } 
} 

IErrorHandler實現:

public class WcfErrorHandler : IErrorHandler 
{ 
    public void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
    { 
     var v = error as DivideByZeroException; 
     if (v != null) 
      fault = Message.CreateMessage(
       version, 
       new FaultException<DivideByZeroException>(v, new FaultReason(v.Message)).CreateMessageFault(), 
       "http://the.fault.action"); 
    } 

    public bool HandleError(Exception error) 
    { 
     return true; 
    } 
} 
+0

後這裏的代碼,請確保它是唯一的_相關代碼。我們不想查看3英里的代碼。 – gunr2171

回答

0

您的ServiceReference在ConsoleApplication1不更新,不包含錯誤契約屬性。當您爲服務和客戶端使用.NET時,最好在它們之間共享DataContract和ServiceContract。

對於測試,您可以在ConsoleApplication1應用程序中引用WcfService1庫。當你這樣做,請按照下列步驟:

  1. 的app.config在ConsoleApplication1:

    <client> 
    
        <endpoint address="net.tcp://localhost/WcfService1/Service1.svc" 
        binding="netTcpBinding" 
        contract="WcfService1.IService1" name="NetTcpBinding_IService2"> 
        </endpoint> 
    
    </client> 
    
  2. 客戶端代碼:

    try 
    { 
        var fact = new ChannelFactory<WcfService1.IService1>("NetTcpBinding_IService2"); 
        var proxy = fact.CreateChannel(); 
        var ves = proxy.GetData(1); 
        Console.WriteLine(ves); 
    
    } 
    catch (FaultException<DivideByZeroException> exp) 
    { 
        Console.WriteLine(exp.Detail); 
    } 
    
  3. 服務代碼(我喜歡捕捉異常之多更接近代碼造成它儘可能,然後拋出一個具體的故障例外):

    public string GetData(int value) 
    {    
        try 
        { 
         int i = 0; 
         int y = 10/i; 
         return string.Format("You entered: {0}", value); 
        } 
        catch (DivideByZeroException d) 
        { 
         throw new FaultException<DivideByZeroException>(d); 
        } 
    } 
    
  4. 你IErrorHandler:

    public class WcfErrorHandler : IErrorHandler 
    { 
        public void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
        { 
    
         if (error is FaultException) 
         { 
          //do nothing as it's already FaultException 
          //you should do a transformation only in the case it's required 
         } 
         else 
         { 
          // Generate fault message manually including the exception as the fault detail 
          MessageFault messageFault = MessageFault.CreateFault(
           new FaultCode("Sender"), 
           new FaultReason(error.Message), 
           error); 
          fault = Message.CreateMessage(version, messageFault, null); 
         } 
        } 
    
        public bool HandleError(Exception error) 
        { 
         //here you can log an exception 
         return true; 
        } 
    } 
    

附:看起來你錯誤地託管了你的服務。爲了測試它,我在ConsoleApplication1中引用了WcfService1。並確實如下:

  1. 將此類行添加到應用程序中。ConsoleApplication1的配置:

    <services> 
        <service name="WcfService1.Service1" behaviorConfiguration="CalculatorServiceBehavior"> 
        <endpoint address="" binding="netTcpBinding" contract="WcfService1.IService1" /> 
        <!--<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" /> --> 
        <host> 
         <baseAddresses> 
         <add baseAddress="net.tcp://localhost/WcfService1/Service1.svc"/> 
         </baseAddresses> 
        </host> 
        </service> 
    </services> 
    
    <behaviors> 
        <serviceBehaviors> 
        <behavior name="CalculatorServiceBehavior"> 
         <serviceDebug includeExceptionDetailInFaults="True" /> 
         <errorHandler /> 
        </behavior> 
        </serviceBehaviors> 
    </behaviors> 
    
    <extensions> 
        <behaviorExtensions> 
        <add name="errorHandler" type="WcfService1.ErrorHandlerExtension, WcfService1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/> 
        </behaviorExtensions> 
    </extensions> 
    
  2. 而且通過客戶端撥打電話到服務之前,我已經開始服務:

    private static void Main(string[] args) 
    { 
        var host = new ServiceHost(typeof(WcfService1.Service1)); 
        host.Open(); 
        ... 
    
相關問題