最近折腾换电脑的事,博客就更新慢了点。好,不废话,直入正题。

前面老周介绍过,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】错误处理(三):错误协定的更多相关文章

  1. [转载]WCF 几种常见错误

    WCF标准的配置文件为: <system.serviceModel>         <services>             <service name=" ...

  2. redis cluster + sentinel详细过程和错误处理三主三备三哨兵

    redis cluster + sentinel详细过程和错误处理三主三备三哨兵1.基本架构192.168.70.215 7001 Master + sentinel 27001192.168.70. ...

  3. WCF分布式开发常见错误解决(1):An error occurred while attempting to find services at...添加服务引用出错

          WCF分布式开发常见错误解决(1):An error occurred while attempting to find services at...添加服务引用出错   当我们在客户端添 ...

  4. Tomcat运行错误示例三

    Tomcat运行错误示例三 最近碰到tomcat启动的问题,如图: 以前也碰见过这种情况,这次写的时候忘记加return,所以跳出了错误,加上之后的效果,如图: 参考网址 参考网址

  5. WCF学习之旅——第一个WCF示例(三)

    第五步:创建客户端 WCF应用服务被成功寄宿后,WCF服务应用便开始了服务调用请求的监听工作.此外,服务寄宿将服务描述通过元数据的形式发布出来,相应的客户端就可以获取这些元数据.接下来我们来创建客户端 ...

  6. WCF学习系列三--【WCF Interview Questions – Part 3 翻译系列】

    http://www.topwcftutorials.net/2012/10/wcf-faqs-part3.html WCF Interview Questions – Part 3 This WCF ...

  7. WCF编程系列(三)地址与绑定

    WCF编程系列(三)地址与绑定   地址     地址指定了接收消息的位置,WCF中地址以统一资源标识符(URI)的形式指定.URI由通讯协议和位置路径两部分组成,如示例一中的: http://loc ...

  8. LabVIEW的错误簇以及错误处理函数

    我们可以在LabVIEW的Modern>>Array, Matrix & Cluster控件面板找到表示错误簇数据类型的错误输入(Error In)以及错误输出(Error Out ...

  9. CAN总线学习记录之三:总线中主动错误和被动错误的通俗解释

    首先建议把广泛使用的"主动错误"和"被动错误"概念换成"主动报错"和"被动报错". 1. 主动报错站点 只要检查到错误, ...

  10. http500:服务器内部错误案例详解(服务器代码语法错误或者逻辑错误)

    http500:服务器内部错误案例详解(服务器代码语法错误或者逻辑错误) 一.总结 服务器内部错误可能是服务器中代码运行的时候的语法错误或者逻辑错误 二.http500:服务器内部错误案例详解 只是一 ...

随机推荐

  1. Ffmpeg 视频教程

    最近一段时间找时间录制了一些Ffmpeg视频教程,还有录制完毕,会持续更新,内容会包含Ffmeg保存文件,网络流转发, 编码,解码,播放器制作,以及服务端搭建等等,适合初学者,有需要的朋友的可以关注: ...

  2. 如何用docker安装laravel开发环境

    如何用docker安装laravel开发环境 看laravel框架的官方文档安装部分时,发现需要安装特别多软件,估计还有许多复杂的配置,官方推荐使用Laravel Homestead虚拟机进行安装,但 ...

  3. [Hadoop] - SSH免密码登录

    在安装hadoop之前需要进行ssh免密码登录,ssh 无密码登录要使用公钥与私钥.linux下可以用用ssh-keygen生成公钥/私钥对,下面我以Redhat为例. 我这里只采用一台机器A(10. ...

  4. C#丨爬虫基础

    在前几天看到一片公众号的文章是关于.NET玩爬虫. 所以今天小编索性来try一下,恰好小编最近在关注房价这一块的,索性就写了一个例子抓取房产信息的. 不善言辞的小编直接给出代码吧!相信读者也等不及了. ...

  5. 响应式布局中的CSS相对量

    一个响应式布局,要能够根据设备屏幕尺寸的改变,动态的调整页面内容,展现不同的设计风格. 在进行响应式的 CSS 代码编写过程中,经常会用到一些相对尺寸,以达到相对定位的目的.例如,常见的响应式布局中需 ...

  6. canvas绘图不清晰的解决方案

    现象描述 同样大小的图片(60x60px)用canvas和DOM绘制,结果发现canvas的画面质量要差很多.结果如下图所示. 上图中,左侧红框中的金币采用DOM绘制,右侧和下方的金币和文字等使用ca ...

  7. mybatis系列笔记(2)---mapper代理方法

    mapper代理方法 在我们在写MVC设计的时候,都会写dao层和daoimp实现层,但假如我们使用mapper代理的方法,我们就可以不用先daoimp实现类 当然这得需要遵守一些相应的规则: (1) ...

  8. sql server中部分函数功能详解

    1.TOP 子句 TOP 子句用于规定要返回的记录的数目. 对于拥有数千条记录的大型表来说,TOP 子句是非常有用的. SQL Server 的语法: SELECT TOP number|percen ...

  9. 《深入理解Java虚拟机》学习笔记之最后总结

    编译器 Java是编译型语言,按照编译的时期不同,编译器可分为: 前端编译器:其实叫编译器的前端更合适些,它把*.java文件转变成*.class文件,如Sun的Javac.Eclipse JDT中的 ...

  10. DOM基础(一)

    在我们刚刚学JavaScript的时候,就应该听说过,JavaScript是由三部分组成的.分别是ECMAScript,DOM和BOM组成的.ECMAScript是JavaScript的核心,它描述了 ...