• WCF服务创建与抛出强类型SOAP Fault


    原创地址:http://www.cnblogs.com/jfzhu/p/4060666.html                 

    转载请注明出处

    前面的文章《WCF服务的异常消息》中介绍过,如果WCF Service发生异常时,Service会将异常序列化为SOAP Fault并发送给客户端。

    默认情况下,出于安全原因,WCF Service中未处理的异常的详细信息不会包括在发送给客户的SOAP Fault里,你只能看到一个通用的SOAP Fault(“The server was unable to process the request due to an internal error.”)。在调试程序的时候,如果想在SOAP Fault中包含异常的详细信息,可以修改服务器的配置文件。

    <behaviors>
      <serviceBehaviors>
        <behavior name="includeExceptionDetails">
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>


     

    SOAP Fault是XML格式,与平台无关。通常一个SOAP Fault包含以下节点

    (1) faultcode

    (2) faultstring

    (3) detail

    Detail节点可以用来包括自定义XML信息。

    WCF Service在发生异常时应抛出FaultException或FaultException<T>,而不应该抛出.NET Exception,出于以下两个原因:

    (1)未处理的.NET Exception会使服务器与客户端之间的channel变为Fault状态,继而导致client proxy无法使用。

    (2).NET Exception只能被.NET平台理解,而FaultException与平台无关。如果想跨平台使用,需要使用FaultException。

    下面还是以中《WCF服务的异常消息》的例子来分别演示如何抛出与处理FaultException与强类型的FaultException<T>。

    (一)使用FaultException

    IDemoService.cs:

    using System.ServiceModel;
    
    namespace WCFDemo 
    {    
        [ServiceContract(Name = "IDemoService")] 
        public interface IDemoService 
        { 
            [OperationContract]        
            int Divide(int numerator, int denominator); 
        } 
    }

    DemoService.cs:

    using System; 
    using System.ServiceModel; 
    using System.ServiceModel.Activation;
    
    namespace WCFDemo 
    { 
        [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
        public class DemoService : IDemoService 
        { 
            public int Divide(int numerator, int denominator) 
            { 
                if (denominator == 0) 
                { 
                    throw new FaultException("Denominator cannot be ZERO!", new FaultCode("DivideByZeroFault")); 
                } 
                return numerator / denominator;           
            } 
        } 
    }

    client:

    private void buttonCalculate_Click(object sender, EventArgs e) 
    { 
        try 
        {                
            textBoxResult.Text = demoServiceClient.Divide(Convert.ToInt32(textBoxNumerator.Text), Convert.ToInt32(textBoxDenominator.Text)).ToString(); 
        } 
        catch (FaultException fault) 
        { 
            MessageBox.Show(fault.Code + " - " + fault.Message); 
        } 
    }

    image

    image

    SOAP Fault XML

    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 
      <s:Body> 
        <s:Fault> 
          <faultcode>s:DivideByZeroFault</faultcode> 
          <faultstring xml:lang="en-US">Denominator cannot be ZERO!</faultstring> 
        </s:Fault> 
      </s:Body> 
    </s:Envelope>

    (二)使用强类型FaultException<T>

    (1)创建一个自定义SOAP Fault类

    DivideByZeroFault.cs:

    using System.Runtime.Serialization;
    
    namespace WCFDemo 
    { 
        [DataContract] 
        public class DivideByZeroFault 
        { 
            [DataMember] 
            public string Error { get; set; }
    
            [DataMember] 
            public string Detail { get; set; } 
        } 
    }

    (2) 在Service方法上使用FaultContractAttribute来指示哪个操作可以使用哪个Fault

    IDemoService.cs:

    using System.ServiceModel;
    
    namespace WCFDemo 
    {    
        [ServiceContract(Name = "IDemoService")] 
        public interface IDemoService 
        { 
            [FaultContract(typeof(DivideByZeroFault))] 
            [OperationContract]        
            int Divide(int numerator, int denominator); 
        } 
    }

    DemoService.cs:

    using System; 
    using System.ServiceModel; 
    using System.ServiceModel.Activation;
    
    namespace WCFDemo 
    { 
        [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
        public class DemoService : IDemoService 
        { 
            public int Divide(int numerator, int denominator) 
            { 
                try 
                { 
                    return numerator / denominator; 
                } 
                catch (DivideByZeroException ex) 
                { 
                    DivideByZeroFault fault = new DivideByZeroFault(); 
                    fault.Error = ex.Message; 
                    fault.Detail = "Denominator cannot be ZERO!"; 
                    throw new FaultException<DivideByZeroFault>(fault); 
                } 
            } 
        } 
    }

    client:

    private void buttonCalculate_Click(object sender, EventArgs e) 
    { 
        try 
        {                
            textBoxResult.Text = demoServiceClient.Divide(Convert.ToInt32(textBoxNumerator.Text), Convert.ToInt32(textBoxDenominator.Text)).ToString(); 
        } 
        catch (FaultException<DemoServiceReference.DivideByZeroFault> fault) 
        { 
            MessageBox.Show(fault.Detail.Error + " - " + fault.Detail.Detail); 
        } 
    }

    image

    image

    返回的SOAP Fault XML:

    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 
      <s:Body> 
        <s:Fault> 
          <faultcode>s:Client</faultcode> 
          <faultstring xml:lang="en-US">The creator of this fault did not specify a Reason.</faultstring> 
          <detail> 
            <DivideByZeroFault xmlns="http://schemas.datacontract.org/2004/07/WCFDemo" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
              <Detail>Denominator cannot be ZERO!</Detail> 
              <Error>Attempted to divide by zero.</Error> 
            </DivideByZeroFault> 
          </detail> 
        </s:Fault> 
      </s:Body> 
    </s:Envelope>

  • 相关阅读:
    Windows 7 Update Settings Disabled (Important Updates Grayed Out)
    vSphere 扩展硬盘空间
    Windows Updateエラー 80072EE2
    how-to-view-source-of-chrome-extension
    ffmpeg 加 logo
    书法字帖 PDF转化为可打印PDF
    远程桌面 函数不受支持
    ico 图标 生成 工具 网站
    WmiPrvSe.exe 的 cpu 占用
    v891 安卓平板的root
  • 原文地址:https://www.cnblogs.com/jfzhu/p/4060666.html
Copyright © 2020-2023  润新知