【WCF】错误处理(三):错误协定
最近折腾换电脑的事,博客就更新慢了点。好,不废话,直入正题。
前面老周介绍过,SOAP消息中的错误信息是用一个 Fault 元素来包装的,前面老周也讲了其中的 FaultCode 元素,即可以对错误信息进行标识。并且也提到了,Fault 元素下的 faultstring 元素就是 FaultReason 所指定的内容。
今天咱们再了解另一个包装元素——detail。可以把 FaultReason 理解为对错误信息的文本概述,而 detail 元素则可以用于错误的详细信息,该元素下面你可以自由地放置XML元素,故灵活性也较强。
于是,detail 元素就与今天所讨论的错误协定扯上关系了。为啥,你想想啊,既然 detail 元素下面可以放XML元素,而数据协定在传输时默认也是使用XML序列化的,所以,所谓错误协定就是一个由开发者自定义的数据协定,可以更灵活地存储错误的详细信息,并且用 detail 元素包装。
理论方面的内容就是上面那点,老周不喜欢故弄玄虚,理论方面的东西都喜欢直接表述,你能看懂就行。
下面,来实例一下,这样你马上就能掌握了。
首先,定义服务协定,这个懂吧。
[ServiceContract(Namespace = "zhou-samples", Name = "demo")]
public interface IDemo
{
[OperationContract(Action = "sqr")]
double SQR(double input);
}
老周打算让这个协定做平方运算,就是传入一个数值,然后返回其平方值,比如,传入3,就返回 3 * 3 = 9。
这个例子的重点是错误协定,其实它就是一个数据协定,我们用下面这个数据协定类来描述错误的详细信息。
[DataContract(Namespace = "zhou-data")]
public class ErrorData
{
[DataMember]
public string ArgName { get; set; }
[DataMember]
public double ErrorVal { get; set; }
[DataMember]
public string CalledAction { get; set; }
}
随便写的,ArgName表示发生错误的参数名,ErrorVal表示出错的值,CalledAction则表示客户端正在调用的服务操要作的 Action 头。
那么,这个错误协定如何与服务协定关联,并且能被 WCF 运行时认识呢,很简单,在刚刚定义的服务协定的方法上,加上一个 FaultContract 特性,并把错误协定的类型关联的Type传递过去。所以,上面的协定代码可以这样改。
[ServiceContract(Namespace = "zhou-samples", Name = "demo")]
public interface IDemo
{
[OperationContract(Action = "sqr")]
[FaultContract(typeof(ErrorData))]
double SQR(double input);
}
这个特性只能用于方法,只能为每个服务操作设定,如果你想统一处理,可以实现 IErrorHandler 接口,这个老周后面再说。
接下来,我们就要实现服务类了。
internal class DemoService : IDemo
{
public double SQR(double input)
{
if (input <= 0d)
{
ErrorData erdata = new ErrorData
{
ArgName = nameof(input),
ErrorVal = input,
CalledAction = OperationContext.Current.IncomingMessageHeaders.Action
};
throw new FaultException<ErrorData>(erdata, "参数必须大于0");
}
return input * input;
}
}
在实现方法中,咱们来个判断,如果传入的值不是大于 0 的,就抛异常。注意,这里因为要用到前面定义的错误协定类型,所以,要用 FaultException 的一个派生类 —— FaultException<TDetail>。这个类只是加了一个泛型参数 TDetail,它就是你要用到的错误协定的类型,所以上面代码是这样抛异常的:
throw new FaultException<ErrorData>(erdata, "参数必须大于0");
ErrorData 就是刚刚上面我们定义的表示错误详细信息的数据协定类。
完事了,就是这样,easy 吧?
于是,在客户端试调用一下,而且传一个不正确的参数进去,并 catch 一下。
IDemo channel = factory.CreateChannel();
try
{
double r = channel.SQR(-1.3d);
Console.WriteLine($"计算结果:{r}");
}
catch(FaultException<ErrorData> fault)
{
string rs = fault.Reason.GetMatchingTranslation().Text;
ErrorData data = fault.Detail;
Console.WriteLine($"错误概要:{rs}");
Console.WriteLine($"发生错误的参数:{data.ArgName}\n错误的值:{data.ErrorVal}\n发生错误的操作:{data.CalledAction}");
}
catch 到异常后,咱们顺便输出到控制台窗口上,以方便观察。注意,FaultException<TDetail> 类的泛型参数可以通过 Detail 属性来获取。
运行这个示例后,服务器收到请求后检测出参数不对,于是抛出异常,错误信息将被封装成这样:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault>
<faultcode xmlns="">s:Client</faultcode>
<faultstring xml:lang="zh-CN" xmlns="">参数必须大于0</faultstring>
<detail xmlns="">
<ErrorData xmlns="zhou-data" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<ArgName>input</ArgName>
<CalledAction>sqr</CalledAction>
<ErrorVal>-1.3</ErrorVal>
</ErrorData>
</detail>
</s:Fault>
</s:Body>
</s:Envelope>
其中,detail 元素中的XML片段为
<detail xmlns="">
<ErrorData xmlns="zhou-data" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<ArgName>input</ArgName>
<CalledAction>sqr</CalledAction>
<ErrorVal>-1.3</ErrorVal>
</ErrorData>
</detail>
这个其实就是把错误协定 XML 序列化后,再放到 detail 元素下。
希望这个如此简单的例子,能让大伙伴们了解错误协定是个啥玩意儿。
示例源代码下载:http://files.cnblogs.com/files/tcjiaan/wcfFaultDetailSample.zip
【WCF】错误处理(三):错误协定的更多相关文章
- [转载]WCF 几种常见错误
WCF标准的配置文件为: <system.serviceModel> <services> <service name=" ...
- redis cluster + sentinel详细过程和错误处理三主三备三哨兵
redis cluster + sentinel详细过程和错误处理三主三备三哨兵1.基本架构192.168.70.215 7001 Master + sentinel 27001192.168.70. ...
- WCF分布式开发常见错误解决(1):An error occurred while attempting to find services at...添加服务引用出错
WCF分布式开发常见错误解决(1):An error occurred while attempting to find services at...添加服务引用出错 当我们在客户端添 ...
- Tomcat运行错误示例三
Tomcat运行错误示例三 最近碰到tomcat启动的问题,如图: 以前也碰见过这种情况,这次写的时候忘记加return,所以跳出了错误,加上之后的效果,如图: 参考网址 参考网址
- WCF学习之旅——第一个WCF示例(三)
第五步:创建客户端 WCF应用服务被成功寄宿后,WCF服务应用便开始了服务调用请求的监听工作.此外,服务寄宿将服务描述通过元数据的形式发布出来,相应的客户端就可以获取这些元数据.接下来我们来创建客户端 ...
- WCF学习系列三--【WCF Interview Questions – Part 3 翻译系列】
http://www.topwcftutorials.net/2012/10/wcf-faqs-part3.html WCF Interview Questions – Part 3 This WCF ...
- WCF编程系列(三)地址与绑定
WCF编程系列(三)地址与绑定 地址 地址指定了接收消息的位置,WCF中地址以统一资源标识符(URI)的形式指定.URI由通讯协议和位置路径两部分组成,如示例一中的: http://loc ...
- LabVIEW的错误簇以及错误处理函数
我们可以在LabVIEW的Modern>>Array, Matrix & Cluster控件面板找到表示错误簇数据类型的错误输入(Error In)以及错误输出(Error Out ...
- CAN总线学习记录之三:总线中主动错误和被动错误的通俗解释
首先建议把广泛使用的"主动错误"和"被动错误"概念换成"主动报错"和"被动报错". 1. 主动报错站点 只要检查到错误, ...
- http500:服务器内部错误案例详解(服务器代码语法错误或者逻辑错误)
http500:服务器内部错误案例详解(服务器代码语法错误或者逻辑错误) 一.总结 服务器内部错误可能是服务器中代码运行的时候的语法错误或者逻辑错误 二.http500:服务器内部错误案例详解 只是一 ...
随机推荐
- IOS缓存管理之PINCache使用
前言: 今年重点在于公司iOS架构的梳理工作,上周整理了http请求接口管理与解耦,接下来准备整理一下项目中的缓存处理,目前项目中使用的是PINCache,去年加入这个开源框架时并没有对这个框架进行了 ...
- 非名校毕业年薪20W程序员 心得分享
大家好,我是落落http://blog.csdn.net/robinson1988/ QQ692162374,其实我选择Oracle是一件很神奇的事情,但是现在回想起来又觉得是命中注定.我2006年就 ...
- [APUE]进程关系(上)
一.终端登录 1. 4.3+BSD终端登录 系统管理员创建一个通常名为/etc/ttys的文件,其中,每个终端设备有一行,每一行说明设备名和传到getty程序的参数,这些参数说明了终端的波特率.当系统 ...
- 微信小程序,超能装的实例教程
序言 开始开发应用号之前,先看看官方公布的「小程序」教程吧!(以下内容来自微信官方公布的「小程序」开发指南) 本文档将带你一步步创建完成一个微信小程序,并可以在手机上体验该小程序的实际效果.这个小程序 ...
- Protege5.0.0入门学习
OWL本体的重要组成部分 Individuals:个体,代表一个领域里面的对象.可以理解成一个类的实例(instances of classes). Properties:属性,是两个个体之间的双重联 ...
- js本地预览图片
废话不说 直接上代码 <script type="text/javascript" src="http://code.jquery.com/jquery-late ...
- oracle commond
常用commond alter user scott account unlock; --解锁账号 alter user scott identified by new_pwd; --设置密码 lsn ...
- 读书笔记 effective c++ Item 29 为异常安全的代码而努力
异常安全在某种意义上来说就像怀孕...但是稍微想一想.在没有求婚之前我们不能真正的讨论生殖问题. 假设我们有一个表示GUI菜单的类,这个GUI菜单有背景图片.这个类将被使用在多线程环境中,所以需要mu ...
- maven springmvc启动问题
1.环境 SpringMVC + Maven + mybatis 2.报错提示 严重: Error configuring application listener of class org.spri ...
- [LeetCode]Spiral Matrix 54
54.Spiral Matrix Given a matrix of m x n elements (m rows, n columns), return all elements of the ma ...