【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:服务器内部错误案例详解 只是一 ...
随机推荐
- 支付宝App支付~关于它的一些坑
坑这个词不仅在微信平台适用,在支付宝也一样的,下面我们来看一下我在做App支付时的一些坑! APP支持流程: 网站H5下单->向支付宝生成订单->回调app的js->app调用支付宝 ...
- java 四则混合运算 计算器
public class Counter { /**用递归算法,把括号内的公式算出然后递归 * @param args */ public static void calculator (St ...
- sping整合hibernate之二:dao层开发
在上一篇日志中将hibernate的会话工厂sessionFactory注入到了spring的容器中,但这样还不够,因为hibernate的增删改查是要使用事务机制的, 所以还要在spring中配置 ...
- [APUE]进程关系(上)
一.终端登录 1. 4.3+BSD终端登录 系统管理员创建一个通常名为/etc/ttys的文件,其中,每个终端设备有一行,每一行说明设备名和传到getty程序的参数,这些参数说明了终端的波特率.当系统 ...
- Windows Form线程同步
.Net多线程开发中,经常需要启动工作线程Worker thread处理某些事情,而工作线程中又需要更新主线程UI thread的界面状态.我们只能在主线程中操作界面控件,否则.Net会抛出异常. 那 ...
- Ubuntu Hash Sum mismatch 解决方法
有时候通过校园网对Ubuntu14.04进行更新时,会出现以下问题: W: Failed to fetch http://xxxxxxx Hash Sum mismatch 解决方法:打开搜索 → ...
- 《深入理解java虚拟机-高效并发》读书笔记
Java内存模型与线程 概述 多任务处理在现代计算机操作系统中几乎已是一项必备的功能,多任务运行是压榨手段,就如windows一样,我们使劲的压榨它运行多个任务,俱要high又要耍.并发则是另外一种更 ...
- chrome浏览器美化插件:让你的浏览器页面冒水泡, 游小鱼儿
下载插件和效果图 这是一个让你的浏览器冒泡泡的插件, 浏览网页的时候仿佛置身于海底世界: 插件下载地址:http://files.cnblogs.com/files/diligenceday/chro ...
- dll
dll可以有一个入口点函数,系统会在不同的时候调用这个入口函数.这个调用是通知性质的,通常被dll用来执行一些与进程或线程有关的初始化和清理工作如果将dll的入口点函数命名为DllMain之外的其他名 ...
- 在Windows平台搭建轻巧的Python开发环境——面向工程和科研的扩展包配置
首先,下载最新版本的Python. 为什么强调最新版本呢,因为新版本的漏洞通常会少得多,而且反映了未来的趋势. 既然要学,何不起点高一点? 官方下载地址:https://www.python.org/ ...