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); } }
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); } }
返回的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>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构