Useful WCF Behaviors - IErrorHandler
Behaviors in WCF are so stinking useful, and once you get past the basics of WCF they're arguably a necessity. Microsoft has saved itself from hundreds of hours of cursing by including the ability to define custom behaviors.
My favorite use of behaviors is addressing some cross cutting concerns that we consistently have in our WCF services. Specifically logging, service registration, wsdl tweaking, and error handling. Which brings us around to the IErrorHandler interface.
Implementing IErrorHandler "Allows an implementer to control the fault message returned to the caller and optionally perform custom error processing such as logging". Thank you MSDN. IErrorHandler has two methods to implement: HandleError, and ProvideFault. Implement them so that they do what they say they do. HandleError should do something with the error (in our case, we log it) and ProvideFault should return a fault message.
#region IErrorHandler Members
// HandleError. Log an error, then allow the error to be handled as usual.
// Return true if the error is considered as already handled
public bool HandleError(Exception error)
{
try
{
\\our loggin service
LoggerClient logger = new LoggerClient(basic, logAddress);
\\build log message
StringBuilder err = new StringBuilder();
err.AppendLine("Source: " + error.Source);
err.AppendLine("Target: " + error.TargetSite.ToString());
err.AppendLine("Message: " + error.Message);
err.AppendLine("Stack Trace: " + error.StackTrace.ToString());
CustomLogEntry log = new CustomLogEntry();
log.AppDomainName = AppDomain.CurrentDomain.FriendlyName;
log.EventId = 900;
log.EventIdSpecified = true;
log.MachineName = Environment.MachineName;
log.Message = err.ToString();
log.Priority = 1;
log.PrioritySpecified = true;
log.Severity = TraceEventType.Error;
log.SeveritySpecified = true;
log.Title = "Exception Caught: " + error.Message;
logger.Log(log);
return true;
}
catch (Exception)
{
throw new Exception("error in the handler");
}
}
public void ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault)
{
// Shield the unknown exception
FaultException faultException = new FaultException(error.Message);
MessageFault messageFault = faultException.CreateMessageFault();
fault = Message.CreateMessage(version, messageFault, faultException.Action);
}
#endregion
Pretty straight forward.
Now we just have to figure out a way to get this to apply to our service, preferably without a lot of extra work. So we don't want to go mucking around with attributes or anything else we have to remember to stick in as we're writing the code. That's where behaviors come in. You can apply them via the config file.
We know we want this particular behavior to apply to our entire service, so we want to implement IServiceBehavior in our class along with IErrorHandler. IServiceBehavior has four methods that we have to implement, but fortunately we can ignore three of them. The one we care about in this case is ApplyDispatchBehavior, where we will apply our error handler to each of the channels in the service. In the example below ErrorHandler is the name of the class we are implementing. Inventive name, isn't it?
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
IErrorHandler errorHandler = new ErrorHandler();
foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
channelDispatcher.ErrorHandlers.Add(errorHandler);
}
}
Great, that's done. Now there's only one thing left to do. We need a class that inherits from BehaviorExtensionElement so that we can add our behavior via configuration. Fortunately BehaviorExtensionElement is a breeze to implement. You need to impelement BehaviorType which just returns the type of your just implement IServiceBehavior class (ErrorHandler above), and CreateBehavior which returns an instantiation of the class.
class ErrorHandlerBehavior : BehaviorExtensionElement
{
public override Type BehaviorType
{
get
{
return typeof(ErrorHandler);
}
} protected override object CreateBehavior()
{
return new ErrorHandler();
}
}
Now the code is done. The last thing to do is to apply the newly created behavior in the config file. Add our new BehaviorExtensionElement to the behaviorExtensions section, and then specify it in the serviceBehaviors section. One important caveat, if includeExceptionDetailInFaults is set to true, then the exception shielding (and I believe Error Handling) will not work.
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="ErrorLogging" type="ErrorHandlerBehavior, ErrorHandling, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8746502a48718374" />
</behaviorExtensions>
</extensions>
<bindings>
<basicHttpBinding>
<binding name="basicBinding">
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="Service1Behavior" name="Service">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicBinding" contract="Service" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Service1Behavior">
<serviceMetadata httpGetUrl="" httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<ErrorLogging />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
There you go. Apply this to all of your WCF services and you won't have to re-invent the wheel again.
Useful WCF Behaviors - IErrorHandler的更多相关文章
- Wcf实现IServiceBehavior拓展机制
IServiceBehavior接口 描述:提供一种在整个服务内修改或插入自定义拓展机制: 命名空间: System.ServiceModel.Description程序集: System.Ser ...
- BizTalk 开发系列(四十) BizTalk WCF-SQL Adapter读取SQL Service Broker消息
SQL Service Broker 是在SQL Server 2005中新增的功能.Service Broker 为 SQL Server 提供队列和可靠的消息传递,可以可用来建立以异步消息为基础的 ...
- 在web.config里使用configSource分隔各类配置
转:http://www.yongfa365.com/Item/using-configSource-Split-Configs.html 大型项目中,可能有多个Service,也就是会有一堆配置,而 ...
- 【WCF】自定义错误处理(IErrorHandler接口的用法)
当被调用的服务操作发生异常时,可以直接把异常的原始内容传回给客户端.在WCF中,服务器传回客户端的异常,通常会使用 FaultException,该异常由这么几个东东组成: 1.Action:在服务调 ...
- WCF扩展系列 - 行为扩展(Behaviors)
原文地址:http://www.cnblogs.com/Creator/archive/2011/05/21/2052687.html 这个系列的第一部分将会重点关注WCF行为(behaviors), ...
- 【WCF】错误处理(四):一刀切——IErrorHandler
前面几篇烂文中所介绍到的错误方式,都是在操作协定的实现代码中抛出 FaultException 或者带泛型参数的detail方案,有些时候,错误的处理方法比较相似,可是要每个操作协定去处理,似乎也太麻 ...
- 利用Attribute和IErrorHandler处理WCF全局异常
在处理WCF异常的时候,有大概几种方式: 第一种是在配置文件中,将includeExceptionDetailInFaults设置为true <behavior name="servi ...
- 【转】WCF扩展系列 - 行为扩展(Behaviors)
原文:https://www.cnblogs.com/Creator/archive/2011/05/21/2052687.html 这个系列的第一部分将会重点关注WCF行为(behaviors),W ...
- WCF入门(22)
前言 本还想写一集WCF入门教程的,心情实在不好,明天又还有面试,改天再写吧. 说一下今天遇到的入职坑.面试能坑,上班能坑,完全没想到入职也能坑.切身经历. 今年10月份想换工作,更新了一下简历,接到 ...
随机推荐
- lfs
LFS──Linux from Scratch,就是一种从网上直接下载源码,从头编译LINUX的安装方式.它不是发行版,只是一个菜谱,告诉你到哪里去买菜(下载源码),怎么把这些生东西( raw c ...
- layui 时间插件laydate ,取消回调
背景:转型新公司不再是做前端展示H5之类的东西,主要业务是后台数据读取和插件搭建前端页面,接触的第一个老项目是layui制作的,由于业务需求,需要用到时间插件以下为时间插件的一些用法--------- ...
- 20164324王启元 Exp1 PC平台逆向破解
一.逆向及Bof基础实践说明 1.1实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. 手工修 ...
- Respone笔记
1 设置定时刷新的头 //设置定时刷新的头 response.setHeader("refresh", "5;url=http://www.baidu.com" ...
- 【CSS】布局之选项卡与图片库
前面对简单的选项卡和简单的图片库进行了实现,现在把两者结合起来,实现下面这样的效果. 现在附上代码: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4 ...
- 【LESS系列】基本语法
这里将直接以实例的方式展示 LESS 的基本语法. less code 是编译前的代码,css code 是编译后的代码. 本文的内容,同样是引自[http://www.ibm.com/develop ...
- golang基础---Slice切片
切片Slice在go语言中是单独的类型(指向底层的数组),不同于python(对可迭代对象操作的工具),注意区分数组和slice的区别 定义一个空slice,格式var s []int,这种既没有长度 ...
- wcf 登录认证 angular 认证重定向
自定义认证管理器,分为两级:1.登陆认证.2.权限认证.权限主要是用户.角色.角色用户关系.功能(系统资源).角色功能关系,5部分决定用户的权限(视图). 两层认证都通过后,更新session的最新交 ...
- MVVMLight - Messenger 1
Messenger Mvvm提倡View和ViewModel的分离,View只负责数据的显示,业务逻辑都尽可能放到ViewModel中, 保持View.xaml.cs中的简洁(没有任何代码,除了构造函 ...
- mybatis学习之CLOB、BLOB处理及多参数方法映射
CLOB数据mysql对应数据类型为longtext.BLOB类型为longblob: model实体: ... private Integer id; private String name; pr ...