Asp.net Web Applicatoin实现自定义HttpModule拦截异常处理
2011-11-12 16:55
756 查看
Asp.net的NamePipe机制给我们提供了很多扩展性.使用HttpModule我们可能实现的有:
强制站点范围的Cookie策略
集中化监控与日志
编写设置与删除HTTP头
控制response输出,如删除多余空白字符
Session管理
认证与受权
下面我们来看如何实现自定义异常处理:
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
上面的代码实现了IHttpModule接口,实现基于HttpApplication.Error事件,接着我们自定义输出了一些信息,包括Form,QueryString.最后把原来的Error信息清除了,这样你看到以前那个黄页了.这个自定义的Module可以用于调试Web应用程序使用.
Web.config中配置:
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
实际开发中,我们可以做的事儿很多,对这些信息记日志,发邮件.如下,我们演示使用EnterpriseLibrary做异常处理并日志记录,部分代码如下:
强制站点范围的Cookie策略
集中化监控与日志
编写设置与删除HTTP头
控制response输出,如删除多余空白字符
Session管理
认证与受权
下面我们来看如何实现自定义异常处理:
publicclassErrorModule:IHttpModule
{
#regionIHttpModuleMembers
///<summary>
///Disposesoftheresources(otherthanmemory)usedbythemodulethatimplements<seecref="T:System.Web.IHttpModule"/>.
///</summary>
publicvoidDispose()
{
//donothing
}
///<summary>
///Initializesamoduleandpreparesittohandlerequests.
///</summary>
///<paramname="context">An<seecref="T:System.Web.HttpApplication"/>thatprovidesaccesstothemethods,properties,andeventscommontoallapplicationobjectswithinanASP.NETapplication</param>
publicvoidInit(HttpApplicationcontext)
{
context.Error+=newEventHandler(customcontext_Error);
}
privatevoidcustomcontext_Error(objectsender,EventArgse)
{
HttpContextctx=HttpContext.Current;
HttpResponseresponse=ctx.Response;
HttpRequestrequest=ctx.Request;
Exceptionexception=ctx.Server.GetLastError();
varsboutput=newStringBuilder();
sboutput.Append("Querystring:<p/>");
//Getoutthequerystring
intcount=request.QueryString.Count;
for(inti=0;i<count;i++)
{
sboutput.AppendFormat("<br/>{0}:--{1}",request.QueryString.Keys[i],request.QueryString[i]);
}
//Getouttheformcollectioninfo
sboutput.Append("<p>-------------------------<p/>Form:<p/>");
count=request.Form.Count;
for(inti=0;i<count;i++)
{
sboutput.AppendFormat("<br/>{0}:--{1}--<br/>",request.Form.Keys[i],request.Form[i]);
}
sboutput.Append("<p>-------------------------<p/>ErrorInfo:<p/>");
sboutput.AppendFormat(@"Yourrequestcouldnotprocessed.Pleasepressthebackbuttononyourbrowserandtryagain.<br/>
Iftheproblempersists,pleasecontacttechnicalsupport<p/>
Informationbelowisfortechnicalsupport:<p/>
<p/>URL:{0}<p/>Stacktrace:---<br/>{1}<p/>InnerException:<br/>{2}"
,ctx.Request.Url,exception.InnerException.StackTrace,exception.InnerException);
response.Write(sboutput.ToString());
//Toletthepagefinishrunningwecleartheerror
ctx.Server.ClearError();
}
#endregion
}
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
上面的代码实现了
Web.config中配置:
<httpModules>
<addname="ErrorLoggingModule"type="MyWeb.ErrorModule"/>
</httpModules>
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
实际开发中,我们可以做的事儿很多,对这些信息记日志,发邮件.如下,我们演示使用
///<summary>
///HandlestheErroreventoftheEntLibLoggingcontrol.
///</summary>
///<paramname="sender">Thesourceoftheevent.</param>
///<paramname="e">The<seecref="System.EventArgs"/>instancecontainingtheeventdata.</param>
///<remarks>authorPetterLiu 'target='_blank'>http://wintersun.cnblogs.com</remarks>privatevoidEntLibLogging_Error(objectsender,EventArgse){varbuilder=newConfigurationSourceBuilder();builder.ConfigureInstrumentation().ForApplicationInstance("MyApp").EnableLogging().EnablePerformanceCounters();//asingleexceptionhandlingpolicynamedMyPolicyforexceptionsoftypeArgumentNullException.//ThehandlerforthisexceptionpolicywilllogtheexceptiontotheGeneralcategory(definedintheLoggingApplicationBlockconfiguration)//asawarningwitheventID9000,wraptheArgumentNullExceptionwithanInvalidOperationException,setthenewexceptionmessagetoMyMessage,andthenre-throwtheexception.builder.ConfigureExceptionHandling().GivenPolicyWithName("MyPolicy").ForExceptionType<ArgumentNullException>().LogToCategory("Exception").WithSeverity(System.Diagnostics.TraceEventType.Warning).UsingEventId(9000).WrapWith<InvalidOperationException>().UsingMessage("MyMessage").ThenNotifyRethrow();//loggingapplicationbuilder.ConfigureLogging().WithOptions.DoNotRevertImpersonation().LogToCategoryNamed("Exception").SendTo.FlatFile("ExceptionLoggingFile").FormatWith(newFormatterBuilder().TextFormatterNamed("TextFormatter").UsingTemplate("Timestamp:{timestamp}{newline}Message:{message}{newline}Category:{category}{newline}")).ToFile("d:\\logs\\ExceptionsLog.log").SendTo.RollingFile("RollingLogfiles").RollAfterSize(1024).ToFile("d:\\logs\\Rollinglog.log").LogToCategoryNamed("General").WithOptions.SetAsDefaultCategory().SendTo.SharedListenerNamed("ExceptionLoggingFile");varconfigSource=newDictionaryConfigurationSource();builder.UpdateConfigurationWithReplace(configSource);EnterpriseLibraryContainer.Current=EnterpriseLibraryContainer.CreateDefaultContainer(configSource);varex=HttpContext.Current.Server.GetLastError();varem=EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>();em.HandleException(ex.InnerException,"MyPolicy");}
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
注意上面的代码,为了运行代码您需要引用以下程序集
EnterpriseLibraryShareCommonLibrary
Microsoft.Practices.ServiceLocationLoggingApplicationBlock ExceptionHandlingApplicationBlock
ExceptionHandlingLoggingProvider
这里我们使用FluentAPI配置,因此没有配置XML文件.所以不需要Web.Config中配置任何信息.代码中有注释.为了测试我们使用一个PAGE故意Throw一个ArgumentNullException.通过
ExceptionLog.log.实际开发你完全按照你的需要来自定义策略.
然后这个日志文件中写出的内容是这样的:
----------------------------------------
Timestamp:2011-11-125:57:08
Message:HandlingInstanceID:a99d005d-5f8d-4613-9522-2d60efb089aa
Anexceptionoftype'System.ArgumentNullException'occurredandwascaught.
----------------------------------------------------------------------------
11/12/201113:57:08
Type:System.ArgumentNullException,mscorlib,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089
Message:Valuecannotbenull.
Parametername:Demoerror
Source:MyWeb
Helplink:
ParamName:Demoerror
Data:System.Collections.ListDictionaryInternal
TargetSite:VoidPage_Load(System.Object,System.EventArgs)
StackTrace:atMyWeb.About.Page_Load(Objectsender,EventArgse)inH:\MyProject\DotNet40\TDD2010\WebHost\MyWeb\About.aspx.cs:line14
atSystem.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtrfp,Objecto,Objectt,EventArgse)
atSystem.Web.Util.CalliEventHandlerDelegateProxy.Callback(Objectsender,EventArgse)
atSystem.Web.UI.Control.OnLoad(EventArgse)
atSystem.Web.UI.Control.LoadRecursive()
atSystem.Web.UI.Page.ProcessRequestMain(BooleanincludeStagesBeforeAsyncPoint,BooleanincludeStagesAfterAsyncPoint)
AdditionalInfo:
MachineName:USER
TimeStamp:2011-11-125:57:08
FullName:Microsoft.Practices.EnterpriseLibrary.ExceptionHandling,Version=5.0.414.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35
AppDomainName:3e5cb21e-3-129655510216406250
ThreadIdentity:
WindowsIdentity:USER\Petter
Category:Exception
由于我们日志模块我们配置还需要写Rollinglog.log文件,内容如下:
----------------------------------------
ExceptionWarning:9000:Timestamp:2011-11-125:57:08
Message:HandlingInstanceID:a99d005d-5f8d-4613-9522-2d60efb089aa
Anexceptionoftype'System.ArgumentNullException'occurredandwascaught.
----------------------------------------------------------------------------
11/12/201113:57:08
Type:System.ArgumentNullException,mscorlib,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089
Message:Valuecannotbenull.
Parametername:Demoerror
Source:MyWeb
Helplink:
ParamName:Demoerror
Data:System.Collections.ListDictionaryInternal
TargetSite:VoidPage_Load(System.Object,System.EventArgs)
StackTrace:atMyWeb.About.Page_Load(Objectsender,EventArgse)inH:\MyProject\DotNet40\TDD2010\WebHost\MyWeb\About.aspx.cs:line14
atSystem.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtrfp,Objecto,Objectt,EventArgse)
atSystem.Web.Util.CalliEventHandlerDelegateProxy.Callback(Objectsender,EventArgse)
atSystem.Web.UI.Control.OnLoad(EventArgse)
atSystem.Web.UI.Control.LoadRecursive()
atSystem.Web.UI.Page.ProcessRequestMain(BooleanincludeStagesBeforeAsyncPoint,BooleanincludeStagesAfterAsyncPoint)
AdditionalInfo:
MachineName:USER
TimeStamp:2011-11-125:57:08
FullName:Microsoft.Practices.EnterpriseLibrary.ExceptionHandling,Version=5.0.414.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35
AppDomainName:3e5cb21e-3-129655510216406250
ThreadIdentity:
WindowsIdentity:USER\Petter
Category:Exception
Priority:0
EventId:9000
Severity:Warning
Title:EnterpriseLibraryExceptionHandling
Machine:USER
AppDomain:3e5cb21e-3-129655510216406250
ProcessId:2444
ProcessName:C:\ProgramFiles\CommonFiles\MicrosoftShared\DevServer\10.0\WebDev.WebServer40.exe
ThreadName:
Win32ThreadId:2748
ExtendedProperties:
----------------------------------------
你可以看到上面的EventId=9000与我们之前在CODE中配置是相同的.
在开源社区有一个组件ELMAH(ErrorLoggingModulesandHandlersforASP.NET),已实现Error处理发邮件,写DB,发送到SNS等功能.我们随意来看下它的代码:
它就是基于IHttpModule的扩展,下面代码来ELMAH:
///<summary>
///Providesanabstractbaseclassfor<seecref="IHttpModule"/>that
///supportsdiscoveryfromwithinpartialtrustenvironments.
///</summary>
publicabstractclassHttpModuleBase:IHttpModule
{
voidIHttpModule.Init(HttpApplicationcontext)
{
if(context==null)
thrownewArgumentNullException("context");
if(SupportDiscoverability)
HttpModuleRegistry.RegisterInPartialTrust(context,this);
OnInit(context);
}
voidIHttpModule.Dispose()
{
OnDispose();
}
///<summary>
///Determineswhetherthemodulewillberegisteredfordiscovery
///inpartialtrustenvironmentsornot.
///</summary>
protectedvirtualboolSupportDiscoverability
{
get{returnfalse;}
}
///<summary>
///Initializesthemoduleandpreparesittohandlerequests.
///</summary>
protectedvirtualvoidOnInit(HttpApplicationapplication){}
///<summary>
///Disposesoftheresources(otherthanmemory)usedbythemodule.
///</summary>
protectedvirtualvoidOnDispose(){}
}
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
这是ErrorLogModule实现之前HttpModuleBase:
publicclassErrorLogModule:HttpModuleBase,IExceptionFiltering
{
publiceventExceptionFilterEventHandlerFiltering;
publiceventErrorLoggedEventHandlerLogged;
///<summary>
///Initializesthemoduleandpreparesittohandlerequests.
///</summary>
protectedoverridevoidOnInit(HttpApplicationapplication)
{
if(application==null)
thrownewArgumentNullException("application");
application.Error+=newEventHandler(OnError);
ErrorSignal.Get(application).Raised+=newErrorSignalEventHandler(OnErrorSignaled);
}
///<summary>
///Getsthe<seecref="ErrorLog"/>instancetowhichthemodule
///willlogexceptions.
///</summary>
protectedvirtualErrorLogGetErrorLog(HttpContextcontext)
{
returnErrorLog.GetDefault(context);
}
///<summary>
///Thehandlercalledwhenanunhandledexceptionbubblesupto
///themodule.
///</summary>
protectedvirtualvoidOnError(objectsender,EventArgsargs)
{
HttpApplicationapplication=(HttpApplication)sender;
LogException(application.Server.GetLastError(),application.Context);
}
///<summary>
///Thehandlercalledwhenanexceptionisexplicitlysignaled.
///</summary>
protectedvirtualvoidOnErrorSignaled(objectsender,ErrorSignalEventArgsargs)
{
LogException(args.Exception,args.Context);
}
///<summary>
///Logsanexceptionanditscontexttotheerrorlog.
///</summary>
protectedvirtualvoidLogException(Exceptione,HttpContextcontext)
{
if(e==null)
thrownewArgumentNullException("e");
//
//Fireaneventtocheckiflistenerswanttofilterout
//loggingoftheuncaughtexception.
//
ExceptionFilterEventArgsargs=newExceptionFilterEventArgs(e,context);
OnFiltering(args);
if(args.Dismissed)
return;
//
//Logaway...
//
ErrorLogEntryentry=null;
try
{
Errorerror=newError(e,context);
ErrorLoglog=GetErrorLog(context);
stringid=log.Log(error);
entry=newErrorLogEntry(log,id,error);
}
catch(ExceptionlocalException)
{
//
//IMPORTANT!Weswallowanyexceptionraisedduringthe
//loggingandsendthemouttothetrace.Theidea
//hereisthatloggingofexceptionsbyitselfshouldnot
//becriticaltotheoveralloperationoftheapplication.
//ThebadthingisthatwecatchANYkindofexception,
//evensystemonesandpotentiallyletthemslipby.
//
Trace.WriteLine(localException);
}
if(entry!=null)
OnLogged(newErrorLoggedEventArgs(entry));
}
///<summary>
///Raisesthe<seecref="Logged"/>event.
///</summary>
protectedvirtualvoidOnLogged(ErrorLoggedEventArgsargs)
{
ErrorLoggedEventHandlerhandler=Logged;
if(handler!=null)
handler(this,args);
}
///<summary>
///Raisesthe<seecref="Filtering"/>event.
///</summary>
protectedvirtualvoidOnFiltering(ExceptionFilterEventArgsargs)
{
ExceptionFilterEventHandlerhandler=Filtering;
if(handler!=null)
handler(this,args);
}
///<summary>
///Determineswhetherthemodulewillberegisteredfordiscovery
///inpartialtrustenvironmentsornot.
///</summary>
protectedoverrideboolSupportDiscoverability
{
get{returntrue;}
}
}
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
更多的功能等待您去挖掘,我们在实际开发中按需选择.希望这篇POST对您开发有帮助. 你可能感兴趣的文章:
在VS2010中配制Elmah邮件发送到Gmail
HttpModule应用:使用HttpModules实现Asp.net离线应用程序 Asp.net使用HttpModule压缩并删除空白Html请求 Asp.net移除Server,X-Powered-By,和X-AspNet-Version头
EnterpriseLibrary:使用Fluent配置API驱动EnterpriseLibrary5.0 EneterpriseLibrary5的Fluent配制API
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
作者:
出处:
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
该文章也同时发布在我的独立博客中-
相关文章推荐
- [Log]ASP.NET之HttpModule拦截404异常
- 基于.Net Framework 4.0 Web API开发(3):ASP.NET Web APIs 异常的统一处理Attribute 和统一写Log 的Attribute的实现
- ASP.Net 重写IHttpModule 来拦截 HttpApplication 实现HTML资源压缩和空白过滤
- 利用 HttpModule,基于输出,统一控制、干预、处理(例如: 过滤关键字、AntiXSS) ASP.Net WebForm Control 展现属性的方案原型
- ASP.Net中自定义Http处理及应用之HttpModule
- asp.net利用自定义Http处理程序实现URL伪静态之初探
- ASP.Net中自定义Http处理及应用之HttpModule篇
- asp.net 利用Web.config的HttpModule 实现整站301永久重定向(简单方便)
- asp.net利用自定义Http处理程序实现URL伪静态之初探
- .net知识系列之七:底层解密(ASP.NET底层之旅,HttpApplication类实例,HttpApplication及Global.asax,实现自定义文件类型处理)
- ASP.NET的(HttpModule,HttpHandler) Asp.net处理模式
- ASP.NET MVC用IHttpModule修改response的html实现压缩或者转繁体,IHttpModule用后台代码注册
- 在Asp.Net中使用HttpModule实现多个域名分别“绑定”到子目录
- visual studio中 用ASP.NET实现 增删改功能实现常见异常及处理
- ASP.NET WebApi 上传文件时异常 Failed to execute send on XMLHttpRequest 的一个处理方法
- asp.net利用HttpModule实现防sql注入
- asp.net IHttpModule实现权限控制
- ASP.Net中自定义Http处理及应用之HttpModule篇
- HttpHand和HttpModule的详细解释,包括Asp.Net对Http请求的处理流程。 .
- Web开发中的缓存技术之三:通过ETag实现缓存处理(ASP.NET MVC版)