在上一篇文章的Controller中我们已经看到了,是怎么使用TYExceptionService进行异常的处理与日志记录,本篇文章具体介绍一下TYExceptionService是如使用Enterprise Library 5.0详细的实现。
因为我们的这个系统是面向接口编程的,所以也需要把TYExceptionService注入到Controller,所以也需要一个ITYExceptionService的接口。
ITYExceptionService异常处理服务接口
这个接口中只有一个方法HandleException,接收一个异常对象,一个Dictionary来存非法的属性和一个字符串message自定义的异常信息。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TYStudioDemo.Interfaces
{
public interface ITYExceptionService
{
string HandleException(Exception exception, Dictionary<string, object> parms, string message);
}
}
实现类TYExceptionService
详细的说明见代码中的注释
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using TYStudioDemo.Interfaces;
using TYStudioDemo.Commons;
namespace TYStudioDemo.Services
{
public class TYExceptionService : ITYExceptionService
{
public string HandleException(Exception exception, Dictionary<string, object> parms, string message)
{
//穿件我们自己定义的异常类
TYException tyException = new TYException(message, exception);
//建立一个StackFrame
StackFrame frame = new StackFrame(1, true);
//记录抛出异常的文件名,方法名和,行号
tyException.SetErrorProperty(TYException.CurrentFilename, frame.GetFileName());
tyException.SetErrorProperty(TYException.CurrentFunction, frame.GetMethod().Name);
tyException.SetErrorProperty(TYException.CurrentLineNumber, frame.GetFileLineNumber().ToString());
// parameters, if present
if (parms != null)
{
foreach (KeyValuePair<string, object> parm in parms)
{
if (parm.Value != null)
{
tyException.SetErrorProperty(parm.Key, parm.Value.ToString());
}
}
}
//使用EntityPrise Library记录异常信息,TYStudioPolicy配置在Web.Config文件中
ExceptionPolicy.HandleException(tyException, "TYStudioPolicy");
//返回有好的错误信息到页面
return tyException.Message;
}
}
}
自定义异常类TYException
见代码注释:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
namespace TYStudioDemo.Commons
{
[Serializable]
public class TYException : Exception
{
//用来记录抛异常的方法,文件名和行号
public static string CurrentFunction = "Function";
public static string CurrentFilename = "Filename";
public static string CurrentLineNumber = "Line Number";
//定义够方法,调用Exception基类的构造方法
public TYException() : base() { }
public TYException(string message) : base(message) { }
public TYException(string message, System.Exception inner) : base(message, inner) { }
protected TYException(SerializationInfo info, StreamingContext context) : base(info, context) { }
//键值对的构造方法
//把键值对存入Data,最终通过Enterprise library text foramtter存入数据库中
public TYException(string message, Exception inner, IDictionary<string, string> props)
: base(message, inner)
{
foreach (KeyValuePair<string, string> entry in props)
if (!String.IsNullOrEmpty(entry.Key) && props[entry.Key] != null)
Data[entry.Key] = entry.Key;
}
//获得错误属性值
public string GetErrorProperty(string key)
{
return (Data[key] == null) ? string.Empty : Data[key].ToString();
}
//添加错误属性值
public void SetErrorProperty(string key, string value)
{
if (!String.IsNullOrEmpty(key) && value != null)
Data[key] = value;
}
}
}
TYStudioDemo.Commons工程,我移除最开始Utilities工程,用这个工程代替了。这里主要放一些公共的类,或者一些工具类。TYException就放在了这里,当然你有好的地方,完全可以放到其他工程。

Enterprise Library配置Web.Config
具体配置内容是由Enterprise Library工具生成的,首先你需要安装Enterprise Library 5.0,下载地址http://entlib./ 。安装完成之后找到安装目录下的C:\Program Files (x86)\Microsoft Enterprise Library 5.0\Bin\EntLibConfig.exe,具体的怎么配置规则不做介绍,可以去网上搜索资料。这里给出一个本系统配置成功之后的截图,和相应的Web.Config代码。点击查看大图

Web.Config文件代码:
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
<section name="exceptionHandling" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration.ExceptionHandlingSettings, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<loggingConfiguration name="" tracingEnabled="true" defaultCategory="Category">
<listeners>
<add name="Database Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.Database.FormattedDatabaseTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging.Database, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Database.Configuration.FormattedDatabaseTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging.Database, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
databaseInstanceName="TYStudioLoggingConnectionString" writeLogStoredProcName="WriteLog"
addCategoryStoredProcName="AddCategory" formatter="Text Formatter"
traceOutputOptions="None" />
</listeners>
<formatters>
<add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
template="Exception Details:
{dictionary({key} - {value}{newline})} 
Message: {message}{newline}
{newline}
Timestamp: {timestamp}{newline}
Category: {category}{newline}
Priority: {priority}{newline}
EventId: {eventid}{newline}
Severity: {severity}{newline}
Title:{title}{newline}
Machine: {localMachine}{newline}"
name="Text Formatter" />
</formatters>
<categorySources>
<add switchValue="All" name="Category">
<listeners>
<add name="Database Trace Listener" />
</listeners>
</add>
</categorySources>
<specialSources>
<allEvents switchValue="All" name="All Events">
<listeners>
<add name="Database Trace Listener" />
</listeners>
</allEvents>
<notProcessed switchValue="All" name="Unprocessed Category">
<listeners>
<add name="Database Trace Listener" />
</listeners>
</notProcessed>
<errors switchValue="All" name="Logging Errors & Warnings">
<listeners>
<add name="Database Trace Listener" />
</listeners>
</errors>
</specialSources>
</loggingConfiguration>
<exceptionHandling>
<exceptionPolicies>
<add name="TYStudioPolicy">
<exceptionTypes>
<add name="All Exceptions" type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
postHandlingAction="None">
<exceptionHandlers>
<add name="Logging Exception Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
logCategory="Category" eventId="100" severity="Error" title="Enterprise Library Exception Handling"
formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling"
priority="0" />
</exceptionHandlers>
</add>
</exceptionTypes>
</add>
</exceptionPolicies>
</exceptionHandling>
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-TYStudioDemo.WebUI-20130331202950;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-TYStudioDemo.WebUI-20130331202950.mdf"
providerName="System.Data.SqlClient" />
<add name="TYEntities" connectionString="metadata=res://*/TYEntities.csdl|res://*/TYEntities.ssdl|res://*/TYEntities.msl;provider=System.Data.SqlClient;provider connection string="data source=localhost;initial catalog=NORTHWND;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
<add name="TYStudioLoggingConnectionString" connectionString="Data Source=localhost;Integrated Security=True;Initial Catalog=TYStudio_Logging;Persist Security Info=True;MultipleActiveResultSets=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
<appSettings>
<add key="webpages:Version" value="2.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
<pages>
<namespaces>
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Optimization" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages" />
<add namespace="TYStudioDemo.DTO" />
</namespaces>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
</entityFramework>
</configuration>
代码上的全都配置好了,现在该是创建数据库的时候了,在安装Enterprise Library的时候,会提示你安装Source选择安装,安装完成之后,我们可以在里面找到数据库的sql文件。天屹在下面的目录里找到了数据库文件,C:\Users\Administrator\Documents\EntLib50Src\Blocks\Logging\Src\DatabaseTraceListener\Scripts\LoggingDatabase.sql,前面系统documents路径根据自己的机器各不相同,自己修改一下。
不知道什么原因,这个默认的数据库和我们的系统不兼容,两个存储过程有问题AddCategory和WriteLog,这两存储过程的参数和mvc内置的有一些出入,所以需要修改一下,下面列出修改的存储过程sql:
AddCategory
USE [TYStudio_Logging]
GO
/****** Object: StoredProcedure [dbo].[AddCategory] Script Date: 04/06/2013 14:46:20 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[AddCategory]
-- Add the parameters for the function here
@categoryName nvarchar(64),
@logID int
AS
BEGIN
SET NOCOUNT ON;
DECLARE @CatID INT
SELECT @CatID = CategoryID FROM Category WHERE CategoryName = @categoryName
IF @CatID IS NULL
BEGIN
INSERT INTO Category (CategoryName) VALUES(@categoryName)
SELECT @CatID = @@IDENTITY
END
EXEC InsertCategoryLog @CatID, @logID
RETURN @CatID
END
WriteLog
USE [TYStudio_Logging]
GO
/****** Object: StoredProcedure [dbo].[WriteLog] Script Date: 04/06/2013 14:48:27 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
/****** Object: Stored Procedure dbo.WriteLog Script Date: 10/1/2004 3:16:36 PM ******/
ALTER PROCEDURE [dbo].[WriteLog]
(
@eventID int,
@priority int,
@severity nvarchar(32),
@title nvarchar(256),
@timestamp datetime,
@machineName nvarchar(32),
@AppDomainName nvarchar(512),
@ProcessID nvarchar(256),
@ProcessName nvarchar(512),
@ThreadName nvarchar(512),
@Win32ThreadId nvarchar(128),
@message nvarchar(1500),
@formattedmessage ntext,
@LogId int OUTPUT
)
AS
INSERT INTO [Log] (
EventID,
Priority,
Severity,
Title,
[Timestamp],
MachineName,
AppDomainName,
ProcessID,
ProcessName,
ThreadName,
Win32ThreadId,
Message,
FormattedMessage
)
VALUES (
@eventID,
@priority,
@severity,
@title,
@timestamp,
@MachineName,
@AppDomainName,
@ProcessID,
@ProcessName,
@ThreadName,
@Win32ThreadId,
@message,
@formattedmessage)
SET @LogId = @@IDENTITY
RETURN @LogId
如果你先麻烦天屹的下篇文章会对整系统做一个总结,并且提供整个系统成型的源代码下载,系统的Commons工程里面会有Logging数据库的备份,你恢复一下也是可以的。
Logging数据库异常信息:
最后让我们来看一眼异常被记录到Logging数据库中的样子吧,这里面有详细的异常信息,还有我们自定义的异常信息,一目了然,当然Enterprise Library也提供出现异常发送邮件的功能,你只需要到Web.Config添加相应的配置就可以了,这样出现异常会第一时间发送到你指定的邮件。
exceptionmessaeg
到这里异常处日志记录处理就完成了。
下篇文章天屹将提供整个系统的代码下载,敬请期待。
|