WCF 服务端异常封装
通常WCF服务端异常的详细信息只有在调试环境下才暴露出来,但我目前有需求需要将一部分异常的详细信息传递到客户端,又需要保证一定的安全性。
最简单的办法当然是在服务端将异常捕获后,序列化传给客户端,但这样需要给服务段方法提供ref或out关键字支持,浪费,不漂亮,所以还是让服务器端抛出异常比较容易。
<service name="HotelService.HotelService" behaviorConfiguration="ServiceExceptionBehavior">
<endpoint address="" binding="basicHttpBinding" contract="HotelService.IHotelService"></endpoint>
<endpoint address="mex" contract="IMetadataExchange" binding="mexHttpBinding"/>
</service>
<!--指定服务的Behavior
将 IncludeExceptionDetailInFaults 设置为 true,可以使异常信息流入客户端,以便进行调试。 此属性需要支持请求响应或双工消息传递的绑定。-->
<behavior name="ServiceExceptionBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
之所以一般服务端异常的细节不提倡暴露出来,主要是因为安全方面的考虑,解决这个问题可以使用自定义异常
public class TestArgumentException : Exception
{
public TestArgumentException(string message, string reason)
: base(message)
{
this.Reason = reason;
} public string Reason { get; private set; }
}
将真正的异常中我需要的异常提取给自定义异常TestArgumentException,然后抛出TestArgumentException
private TestArgumentException BuildNewException(ArgumentException exception)
{
TestArgumentException testException = new TestArgumentException(exception.Message, exception.Source);
return testException;
}
将真实的异常替换为自定义异常应该是在发生异常后,异常消息返回之前,可以通过实现IErrorHandler的ProvideFault方法来达到目的,如果需要传递真实的异常类型可以使用FaultCode传递
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
if (fault == null)
{
if (error is ArgumentException)
{
TestArgumentException testException = BuildNewException(error as ArgumentException);
FaultCode code = FaultCode.CreateReceiverFaultCode(new FaultCode("ArgumentException"));
ExceptionDetail detail = new ExceptionDetail(testException);
FaultException exceptionMessage = new FaultException<ExceptionDetail>(detail, testException.Reason, code);
MessageFault message = exceptionMessage.CreateMessageFault();
fault = Message.CreateMessage(version, message, exceptionMessage.Action);
}
}
}
通过IServiceBehavior的ApplyDispatchBehavior
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher epd in dispatcher.Endpoints)
{
if (epd.ContractName == "IHotelService")
{
dispatcher.ErrorHandlers.Add(new ServiceErrorHandler());
}
}
}
}
就可以达到目的了。
客户端测试代码:
bool isException = false;
HotelService.HotelServiceClient proxy = new HotelService.HotelServiceClient();
try
{
proxy.GetData();
}
catch (FaultException<ExceptionDetail> ee)
{
isException = true;
string s = String.Format("{0}\r\nERROR:{1}", ee.GetType(), ee.Detail.Message);
MessageBox.Show(s);
}
catch (FaultException ee)
{
isException = true;
string s = String.Format("{0}\r\nERROR:{1}", ee.GetType(), ee.Message);
MessageBox.Show(s);
}
finally
{
if (isException)
{
//注:在catch程序块中,我们通过代码((calculator as ICommunicationObject).Abort();)
//将会话信道强行中断。原因在于,对于基于会话信道(Sessionful Channel)的服务调用,
//服务端抛出的异常会将该信道的状态转变为出错状态(Faulted),处于Faulted状态的会话信道将不能再用于后续的通信
//即使你调用Close方法将其关闭。在这种情况下,需要调用Abort方法对其进行强行中止。
proxy.Abort();
}
else
{
proxy.Close();
}
}
这里还有一点问题:FaultException<ExceptionDetail>可以将详细的信息完整的以我想要的格式传到客户端,但ExceptionDetail的派生类会丢失很多信息并且不能被
catch (FaultException<ExceptionDetail> ee)捕获到,应该没加KownType的关系,有空试下。
将以上代码封装到一个类库中,可以让所有符合规则的WCF服务继承,达到我的目的。
目前有一点始终不满意,这个DLL的名字想不出起什么好。。。
WCF 服务端异常封装的更多相关文章
- WCF客户端获取服务端异常[自定义异常]
引言 经过不断的摸索,询问/调试,终于学会了关于WCF客户端与服务端之间异常的处理机制,在此来记录自己的成果,用于记录与分享给需要的伙伴们. 首先感谢[.NET技术群]里群主[轩]的大力帮助,如有需要 ...
- WCF服务端开发和客户端引用小结
1.服务端开发 1.1 WCF服务创建方式 创建一个WCF服务,总是会创建一个服务接口和一个服务接口实现.通常根据服务宿主的不同,有两种创建方式. (1)创建WCF应用程序 通过创建WCF服务应用程序 ...
- WCF服务端调用client.
wcf服务端 1,新建一个"windows窗口程序"名称为WCFServer2. 2.然后加入一个"WCF服务"名称为Service1. 详细步骤为:解决方式试 ...
- 在Unity3D中连接WCF服务端
服务端不多讲解,有一处需要改的地方.具体服务端请看WCF入门学习2-控制台做为宿主 建议实际项目不要拿去用,毕竟是mono不是原生.net.或许是个坑 由于Unity的mono版本问题不能直接用net ...
- WCF服务端行为的一些设置
[ServiceBehavior( InstanceContextMode = InstanceContextMode.Single, //表示所有的请求都用一个服务实例来处理 Concurren ...
- WCF服务端与客户端时间匹配问题
当服务端部署的WCF服务服务在被客户机调用时,如果显示: 错误,展开后,详细错误为:An error occurred when verifying security for the message ...
- WCF服务端返回:(413) Request Entity Too Large
出现这个原因我们应该都能猜测到,文件传出过大,超出了WCF默认范围,那么我们需要进行修改. 服务端和客户端都需要修改. 第一.客户端: <system.serviceModel> < ...
- WCF服务端的.NET Core支持项目Core WCF 正式启动
长期以来在wcf客户端库 https://github.com/dotnet/wcf 里反应最强烈的就是.NET Core的服务端支持 https://github.com/dotnet/wcf/is ...
- 保持WCF服务端与客户端的长连接
背景 客户端与服务端使用WCF建立连接后:1.可能长时间不对话(调用服务操作):2.客户端的网络不稳定. 为服务端与客户端两边都写“心跳检测”代码?不愿意. 解决 设置inactivityTimeou ...
随机推荐
- Android 源代码结构(转)
简介 在使用Andriod SDK进行应用程序开发的时候,我们需要对源代码进行调试,有可能需要进入到某个Android API函数内部进行跟踪调试.但是,如果目标版本的SDK没有关联对应版本的源代码的 ...
- poj 3975&&hdu 1850 (nim)
//赢得了上风 //从n几年移除堆叠一堆石头,有多少可取的石头堆 # include <stdio.h> # include <string.h> # include < ...
- HDU 4081-Parsing URL(水)
Parsing URL Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others) Tota ...
- 利用纯CSS3实现超立体的3D图片侧翻倾斜效果
原文:利用纯CSS3实现超立体的3D图片侧翻倾斜效果 上午的时候我在jQuery论坛上看到网友分享的一款CSS3 3D图片侧翻倾斜特效,觉得效果非常棒,其实话说回来,这玩意儿的实现真的非常简单,主要是 ...
- log4j的配置信息(转)
首先,在项目中的classes 中新建立一个log4j.properties文件即可: 在实际编程时,要使Log4j真正在系统中运行事先还要对配置文件进行定义.定义步骤就是对Logger.Append ...
- Maven学习笔记(四):协调和依赖
Maven协调具体的解释: Maven定义了这样一组规则:世界上不论什么一个构件都能够使用Maven坐标唯一标识.Maven坐标的元素包含groupId.artifactId.version ...
- Nyoj 一笔画问题(图论)
描述 zyc从小就比较喜欢玩一些小游戏,其中就包括画一笔画,他想请你帮他写一个程序,判断一个图是否能够用一笔画下来. 规定,所有的边都只能画一次,不能重复画. 输入 第一行只有一个正整数N(N&l ...
- VC中MessageBox的常见用法
一.关于MessageBox 消息框是个很常用的控件,属性比较多,本文列出了它的一些常用方法,及指出了它的一些应用场合. 1.MessageBox("这是一个最简单的 ...
- 一款非常棒的纯CSS3 3D菜单演示及制作教程
原文:一款非常棒的纯CSS3 3D菜单演示及制作教程 这段时间比较忙,很久没在这里分享一些漂亮的HTML5和CSS3资源了,今天起的早,看到一款很不错的CSS3 3D菜单,觉得非常上眼,就将它分享给大 ...
- 【专访】【Spring常见问题汇总】【05】
种: 传播行为:传播行为定义了client与彼调用方法之间的事务边界. 隔离级别:隔离级别定义了一个事务可能受其它并发事务影响的程度. 仅仅读:表明事务是否是仅仅读的. 事务超时:指定事务执行的最长时 ...