WCF初探-20:WCF错误协定
WCF错误协定概述
- 在所有托管应用程序中,处理错误由 Exception 对象表示。 在基于 SOAP 的应用程序(如 WCF 应用程序)中,服务方法使用 SOAP 错误消息来传递处理错误信息。 SOAP 错误是包括在服务操作元数据中的消息类型,因此会创建一个错误协定,客户端可使用该协定来使操作更加可靠或更具交互性。 此外,由于 SOAP 错误在客户端以 XML 格式表示,这是一种任何 SOAP 平台上的客户端都可以使用的具有极好的互操作性的类型系统,可增加 WCF 应用程序的适用范围。
- 由于 WCF 应用程序在两种类型的错误系统下都可运行,因此发送到客户端的任何托管异常信息都必须在服务上从异常转换为 SOAP 错误,并在 WCF 客户端中从 SOAP 错误转换为错误异常。 对于双工客户端,客户端协定还可以将 SOAP 错误发送回服务。 在任一种情况下,您都可以使用默认的服务异常行为,或者可以显式控制是否(以及如何)将异常映射到错误消息。
- 可以发送两种类型的 SOAP 错误:已声明的和未声明的。 已声明的 SOAP 错误是指其中的某个操作具有 System.ServiceModel.FaultContractAttribute 属性(用于指定自定义 SOAP 错误类型)的错误。 未声明的 SOAP 错误是在操作的协定中没有指定的错误。
创建错误协定
- 要实现错误协定传递到客户端,首先需要将将 ServiceBehaviorAttribute.IncludeExceptionDetailInFaults 或 ServiceDebugBehavior.IncludeExceptionDetailInFaults 设置为 true(可以在服务配置文件中指定)。
- 定义错误协定时,我们通常是自定义错误信息显示。通常我们将需要显示的错误信息定义为数据协定,再使用FaultContractAttribute在操作协定上进行标记类型为哪一种数据协定的错误。
- 操作过程中发生托管异常时将引发 FaultException<TDetail>(此处类型参数为可序列化的错误信息)。 WCF 客户端应用程序呈现的 SOAP 错误类型与客户端实现中引发的类型相同,即FaultException<TDetail>(此处类型参数为可序列化的错误信息)。 FaultContractAttribute 只能用来为双向服务操作和异步操作对指定 SOAP 错误;单向操作并不支持 SOAP 错误,因而不支持 FaultContractAttribute。
WCF错误协定示例
- 解决方法结构如下:
- 工程结构说明:
- Service:类库程序,WCF服务端程序。在服务协定接口ISampleService.cs中定义了数据协定FaultMessage来显示错误的时间和信息,在操作协定SampleMethod上,我们用FaultContract来标记错误协定的类型为FaultMessage。在实现操作协定方法SampleMethod中,我们可以利用FaultException<FaultMessage>来自定义错误,抛出自定义异常信息。在客户端利用FaultException<FaultMessage>中的Detail可以获取包含详细错误信息的对象。ISampleService.cs的代码如下:
- using System.ServiceModel;
- using System.Runtime.Serialization;
- namespace Service
- {
- [ServiceContract]
- public interface ISampleService
- {
- [OperationContract]
- [FaultContract(typeof(FaultMessage))]
- string SampleMethod(string msg);
- }
- [DataContract]
- public class FaultMessage
- {
- private string _errorTime;
- private string _errorMessage;
- [DataMember]
- public string ErrorTime
- {
- get { return this._errorTime; }
- set { this._errorTime = value; }
- }
- [DataMember]
- public string ErrorMessage
- {
- get { return this._errorMessage; }
- set { this._errorMessage = value; }
- }
- public FaultMessage(string time,string message)
- {
- this._errorTime = time;
- this._errorMessage = message;
- }
- }
- }
SampleService.cs的代码如下:
- using System.ServiceModel;
- namespace Service
- {
- public class SampleService :ISampleService
- {
- public string SampleMethod(string msg)
- {
- if (msg.Length < )
- {
- return "输入的字符串为" + msg;
- }
- else
- {
- throw new FaultException<FaultMessage>(
- new FaultMessage("错误时间:" + System.DateTime.Now.ToString(), "输入的【" + msg + "】字符串大于10个字符"));
- }
- }
- }
- }
2. Host:控制台应用程序,服务承载程序。添加对程序集Service的引用,完成以下代码,寄宿服务。Program.cs代码如下:
- using System;
- using System.ServiceModel;
- using Service;
- namespace Host
- {
- class Program
- {
- static void Main(string[] args)
- {
- using (ServiceHost host = new ServiceHost(typeof(SampleService)))
- {
- host.Opened += delegate { Console.WriteLine("服务已经启动,按任意键终止!"); };
- host.Open();
- Console.Read();
- }
- }
- }
- }
App.config代码如下:
- <?xml version="1.0"?>
- <configuration>
- <system.serviceModel>
- <services>
- <service name="Service.SampleService" behaviorConfiguration="mexBehavior">
- <host>
- <baseAddresses>
- <add baseAddress="http://localhost:1234/SampleService/"/>
- </baseAddresses>
- </host>
- <endpoint address="" binding="wsHttpBinding" contract="Service.ISampleService" />
- <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
- </service>
- </services>
- <behaviors>
- <serviceBehaviors>
- <behavior name="mexBehavior">
- <serviceMetadata httpGetEnabled="true"/>
- <serviceDebug includeExceptionDetailInFaults="true"/>
- </behavior>
- </serviceBehaviors>
- </behaviors>
- </system.serviceModel>
- </configuration>
我们通过svcutil.exe工具生成客户端代理类和客户端的配置文件
svcutil.exe是一个命令行工具,位于路径C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin下,我们可以通过命令行运行该工具生成客户端代理类
- 在运行中输入cmd打开命令行,输入 cd C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin
- 输入svcutil.exe /out:f:\ SampleServiceClient.cs /config:f:\App.config http://localhost:1234/ SampleService
3. Client:控制台应用程序,客户端调用程序。将生成的UserInfoClient.cs和App.config复制到Client的工程目录下,完成客户端调用代码。Program.cs的代码如下:
- using System;
- using System.ServiceModel;
- using Service;
- namespace Client
- {
- class Program
- {
- static void Main(string[] args)
- {
- SampleServiceClient proxy = new SampleServiceClient();
- try
- {
- Console.WriteLine(proxy.SampleMethod("WCF"));
- Console.WriteLine(proxy.SampleMethod("Windows Communication Foundation"));
- }
- catch (FaultException<FaultMessage> ex)
- {
- Console.WriteLine(ex.Detail.ErrorTime+"\n"+ex.Detail.ErrorMessage);
- }
- finally
- {
- Console.Read();
- }
- }
- }
- }
程序运行结果如下:
总结
- 通常我们在服务端通过FaultException抛出异常信息,然后就可以在客户端进行处理,即使我们不加FaultContract特性。参照:WCF初探-12:WCF客户端异常处理
- 我们也可以通过添加ServiceBehavior特性,将服务的IncludeExceptionDetailInFaults设置为true(默认为 false),客户端也可以捕获抛出的非FaultException异常信息,但该异常仍然会导致通道出现错误。
- 在本示例中,我们实现了错误协定的自定义错误信息操作。其中最重要的FaultException<TDetail>,通过TDetail类型,我们可以把自定义的数据协定错误信息在服务端客户端进行序列化和反序列化,最终实现SOAP消息的错误信息的传递。
WCF初探-20:WCF错误协定的更多相关文章
- WCF初探文章列表
WCF初探-1:认识WCF WCF初探-6:WCF服务配置 WCF初探-2:手动实现WCF程序 WCF初探-7:WCF服务配置工具使用 WCF初探-3:WCF消息交换模式之单向模式 WCF初探-8:W ...
- WCF初探-14:WCF服务协定
前言: 在前面的文章中,我们定义的服务协定上都会有一个ServiceContract的特性来修饰,这是因为服务契约的实现要靠ServiceContractAttribute 属性定义,然后使用一个或多 ...
- WCF初探-15:WCF操作协定
前言: 在前面的文章中,我们定义服务协定时,在它的操作方法上都会加上OperationContract特性,此特性属于OperationContractAttribute 类,将OperationCo ...
- 【WCF】错误协定声明
在上一篇烂文中,老周给大伙伴们介绍了 IErrorHandler 接口的使用,今天,老周补充一个错误处理的知识点——错误协定. 错误协定与IErrorHandler接口不同,大伙伴们应该记得,上回我们 ...
- 【WCF】错误处理(三):错误协定
最近折腾换电脑的事,博客就更新慢了点.好,不废话,直入正题. 前面老周介绍过,SOAP消息中的错误信息是用一个 Fault 元素来包装的,前面老周也讲了其中的 FaultCode 元素,即可以对错误信 ...
- WCF初探-10:WCF客户端调用服务
创建WCF 服务客户端应用程序需要执行下列步骤: 获取服务终结点的服务协定.绑定以及地址信息 使用该信息创建 WCF 客户端 调用操作 关闭该 WCF 客户端对象 WCF客户端调用服务存在以下特点: ...
- WCF初探-22:WCF中使用Message类(上)
前言 从我们学习WCF以来,就一直强调WCF是基于消息的通信机制.但是由于WCF给我们做了高级封装,以至于我们在使用WCF的时候很少了解到消息的内部机制.由于WCF的架构的可扩展性,针对一些特殊情况, ...
- WCF初探-26:WCF中的会话
理解WCF中的会话机制 在WCF应用程序中,会话将一组消息相互关联,从而形成对话.会话”是在两个终结点之间发送的所有消息的一种相互关系.当某个服务协定指定它需要会话时,该协定会指定所有调用(即,支持调 ...
- WCF初探-13:WCF客户端为双工服务创建回调对象
前言: 在WCF初探-5:WCF消息交换模式之双工通讯(Duplex)博文中,我讲解了双工通信服务的一个应用场景,即订阅和发布模式,这一篇,我将通过一个消息发送的例子讲解一下WCF客户端如何为双工服务 ...
随机推荐
- 自动化环境robot framework安装中问题解决
在搭建自动化环境的时候需要安装以下程序:
- [CrunchBang]修改win+ubuntu 双 系统菜单的 启动顺序 引导
说到启动就不得不说GRUB,Linux下大名鼎鼎的启动管理工具(曾经的LILO已经风光不再),当然现在已经是GRUB2了,GRUB2和GRUB最重要的区别就是,GRUB存放系统启动信息的文件为/boo ...
- 在C#中??和?分别是什么意思?
在C# 6.0中,引入了一个 ?. 的运算符,前面的代码可以改成如下形式: int? firstX = points?.FirstOrDefault()?.X; 从这个例子中我们也可以看出它的基本用法 ...
- Css Study - Top Menu in Header 横向间隔的菜单
.shortcut ul li { display: inline; } CSS <style> ol, ul { list-style: none; } html, body, ul, ...
- js中==, !==, === ,!=的区别
在讨论比较符的时候我们先要来讨论哈js的类型,这样有助于我们从本质上了解原理. 下面是我找的资料加上个人的总结: js中有5种数据类型:Undefined.Null.Boolean.Number和St ...
- Windows Store Apps, Error: The certificate specified has expired.(转)
Windows Store Apps, Error: The certificate specified has expired. 0 comments|Posted on October 7th, ...
- mysql中查询语句中的一个知识点说明
1, 简单说明. select * from tb_name where 1[不为零即可];则会显示所有记录,select * from tb_name where 0;则不显示任何记录 假设数据库中 ...
- php多维数组去除空元素
在php中去除数组中的空值可以使用array_filter() 这个函数 但是这个函数只能对一维数组起作用,一旦需要对多维数组去空就不行了,而且去除的空也包括(int)0,(string)0,使用起来 ...
- php无限遍历目录-修正版
最近在能php目录操作,搞了一个目录无限遍历: 使用的函数有: isset()判断某个变量是否定义 chdir() 将当前目录改变为指定的目录. opendir() 打开目录. readdir()读取 ...
- Autofac 解释第一个例子 《第一篇》
Autofac是一个轻量级的依赖注入的框架,同类型的框架还有Spring.NET,Unity,Castle等. Autofac的使用有一个非常让人郁闷的地方,就是服务器要求安装有Microsoft . ...