分享

使用StructureMap扩展ASP.NET MVC三层架构6

 ThinkTank_引擎 2014-02-03

在上一篇文章的Controller中我们已经看到了,是怎么使用TYExceptionService进行异常的处理与日志记录,本篇文章具体介绍一下TYExceptionService是如使用Enterprise Library 5.0详细的实现。

因为我们的这个系统是面向接口编程的,所以也需要把TYExceptionService注入到Controller,所以也需要一个ITYExceptionService的接口。

ITYExceptionService异常处理服务接口

这个接口中只有一个方法HandleException,接收一个异常对象,一个Dictionary来存非法的属性和一个字符串message自定义的异常信息。

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace TYStudioDemo.Interfaces
  7. {
  8.     public interface ITYExceptionService
  9.     {
  10.         string HandleException(Exception exception, Dictionary<string, object> parms, string message);
  11.     }
  12. }

实现类TYExceptionService

详细的说明见代码中的注释

  1. using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.Linq;
  6. using System.Runtime.Serialization;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using TYStudioDemo.Interfaces;
  10. using TYStudioDemo.Commons;
  11. namespace TYStudioDemo.Services
  12. {
  13.     public class TYExceptionService : ITYExceptionService
  14.     {
  15.         public string HandleException(Exception exception, Dictionary<string, object> parms, string message)
  16.         {
  17.             //穿件我们自己定义的异常类
  18.             TYException tyException = new TYException(message, exception);
  19.             //建立一个StackFrame
  20.             StackFrame frame = new StackFrame(1, true);
  21.             //记录抛出异常的文件名,方法名和,行号
  22.             tyException.SetErrorProperty(TYException.CurrentFilename, frame.GetFileName());
  23.             tyException.SetErrorProperty(TYException.CurrentFunction, frame.GetMethod().Name);
  24.             tyException.SetErrorProperty(TYException.CurrentLineNumber, frame.GetFileLineNumber().ToString());
  25.             // parameters, if present
  26.             if (parms != null)
  27.             {
  28.                 foreach (KeyValuePair<string, object> parm in parms)
  29.                 {
  30.                     if (parm.Value != null)
  31.                     {
  32.                         tyException.SetErrorProperty(parm.Key, parm.Value.ToString());
  33.                     }
  34.                 }
  35.             }
  36.             //使用EntityPrise Library记录异常信息,TYStudioPolicy配置在Web.Config文件中
  37.             ExceptionPolicy.HandleException(tyException, "TYStudioPolicy");
  38.             //返回有好的错误信息到页面
  39.             return tyException.Message;
  40.         }
  41.     }
  42. }

自定义异常类TYException

见代码注释:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.Serialization;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace TYStudioDemo.Commons
  8. {
  9.     [Serializable]
  10.     public class TYException : Exception
  11.     {
  12.         //用来记录抛异常的方法,文件名和行号
  13.         public static string CurrentFunction = "Function";
  14.         public static string CurrentFilename = "Filename";
  15.         public static string CurrentLineNumber = "Line Number";
  16.         //定义够方法,调用Exception基类的构造方法
  17.         public TYException() : base() { }
  18.         public TYException(string message) : base(message) { }
  19.         public TYException(string message, System.Exception inner) : base(message, inner) { }
  20.         protected TYException(SerializationInfo info, StreamingContext context) : base(info, context) { }
  21.         //键值对的构造方法
  22.         //把键值对存入Data,最终通过Enterprise library text foramtter存入数据库中
  23.         public TYException(string message, Exception inner, IDictionary<string, string> props)
  24.             : base(message, inner)
  25.         {
  26.             foreach (KeyValuePair<string, string> entry in props)
  27.                 if (!String.IsNullOrEmpty(entry.Key) && props[entry.Key] != null)
  28.                     Data[entry.Key] = entry.Key;
  29.         }
  30.         //获得错误属性值
  31.         public string GetErrorProperty(string key)
  32.         {
  33.             return (Data[key] == null) ? string.Empty : Data[key].ToString();
  34.         }
  35.         //添加错误属性值
  36.         public void SetErrorProperty(string key, string value)
  37.         {
  38.             if (!String.IsNullOrEmpty(key) && value != null)
  39.                 Data[key] = value;
  40.         }
  41.     }
  42. }

TYStudioDemo.Commons工程,我移除最开始Utilities工程,用这个工程代替了。这里主要放一些公共的类,或者一些工具类。TYException就放在了这里,当然你有好的地方,完全可以放到其他工程。

mvc-structuremap-commons

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代码。点击查看大图

enterprise-library-config

Web.Config文件代码:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!--
  3.  For more information on how to configure your ASP.NET application, please visit
  4. http://go.microsoft.com/fwlink/?LinkId=169433
  5.  -->
  6. <configuration>
  7.   <configSections>
  8.     <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
  9.     <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" />
  10.     <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" />
  11.     <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  12.   </configSections>
  13.   <loggingConfiguration name="" tracingEnabled="true" defaultCategory="Category">
  14.     <listeners>
  15.       <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"
  16.        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Database.Configuration.FormattedDatabaseTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging.Database, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
  17.        databaseInstanceName="TYStudioLoggingConnectionString" writeLogStoredProcName="WriteLog"
  18.        addCategoryStoredProcName="AddCategory" formatter="Text Formatter"
  19.        traceOutputOptions="None" />
  20.     </listeners>
  21.     <formatters>
  22.       <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
  23.        template="Exception Details:&#xA;{dictionary({key} - {value}{newline})}  &#xA;Message: {message}{newline}&#xA;{newline}&#xA;Timestamp: {timestamp}{newline}&#xA;Category: {category}{newline}&#xA;Priority: {priority}{newline}&#xA;EventId: {eventid}{newline}&#xA;Severity: {severity}{newline}&#xA;Title:{title}{newline}&#xA;Machine: {localMachine}{newline}"
  24.        name="Text Formatter" />
  25.     </formatters>
  26.     <categorySources>
  27.       <add switchValue="All" name="Category">
  28.         <listeners>
  29.           <add name="Database Trace Listener" />
  30.         </listeners>
  31.       </add>
  32.     </categorySources>
  33.     <specialSources>
  34.       <allEvents switchValue="All" name="All Events">
  35.         <listeners>
  36.           <add name="Database Trace Listener" />
  37.         </listeners>
  38.       </allEvents>
  39.       <notProcessed switchValue="All" name="Unprocessed Category">
  40.         <listeners>
  41.           <add name="Database Trace Listener" />
  42.         </listeners>
  43.       </notProcessed>
  44.       <errors switchValue="All" name="Logging Errors & Warnings">
  45.         <listeners>
  46.           <add name="Database Trace Listener" />
  47.         </listeners>
  48.       </errors>
  49.     </specialSources>
  50.   </loggingConfiguration>
  51.   <exceptionHandling>
  52.     <exceptionPolicies>
  53.       <add name="TYStudioPolicy">
  54.         <exceptionTypes>
  55.           <add name="All Exceptions" type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  56.            postHandlingAction="None">
  57.             <exceptionHandlers>
  58.               <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"
  59.                logCategory="Category" eventId="100" severity="Error" title="Enterprise Library Exception Handling"
  60.                formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling"
  61.                priority="0" />
  62.             </exceptionHandlers>
  63.           </add>
  64.         </exceptionTypes>
  65.       </add>
  66.     </exceptionPolicies>
  67.   </exceptionHandling>
  68.   <connectionStrings>
  69.     <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"
  70.      providerName="System.Data.SqlClient" />
  71.     <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""
  72.      providerName="System.Data.EntityClient" />
  73.     <add name="TYStudioLoggingConnectionString" connectionString="Data Source=localhost;Integrated Security=True;Initial Catalog=TYStudio_Logging;Persist Security Info=True;MultipleActiveResultSets=True"
  74.      providerName="System.Data.SqlClient" />
  75.   </connectionStrings>
  76.   <appSettings>
  77.     <add key="webpages:Version" value="2.0.0.0" />
  78.     <add key="webpages:Enabled" value="false" />
  79.     <add key="PreserveLoginUrl" value="true" />
  80.     <add key="ClientValidationEnabled" value="true" />
  81.     <add key="UnobtrusiveJavaScriptEnabled" value="true" />
  82.   </appSettings>
  83.   <system.web>
  84.     <compilation debug="true" targetFramework="4.5" />
  85.     <httpRuntime targetFramework="4.5" />
  86.     <authentication mode="Forms">
  87.       <forms loginUrl="~/Account/Login" timeout="2880" />
  88.     </authentication>
  89.     <pages>
  90.       <namespaces>
  91.         <add namespace="System.Web.Helpers" />
  92.         <add namespace="System.Web.Mvc" />
  93.         <add namespace="System.Web.Mvc.Ajax" />
  94.         <add namespace="System.Web.Mvc.Html" />
  95.         <add namespace="System.Web.Optimization" />
  96.         <add namespace="System.Web.Routing" />
  97.         <add namespace="System.Web.WebPages" />
  98.         <add namespace="TYStudioDemo.DTO" />
  99.       </namespaces>
  100.     </pages>
  101.   </system.web>
  102.   <system.webServer>
  103.     <validation validateIntegratedModeConfiguration="false" />
  104.     <handlers>
  105.       <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
  106.       <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
  107.       <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  108.       <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" />
  109.       <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" />
  110.       <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" />
  111.     </handlers>
  112.   </system.webServer>
  113.   <runtime>
  114.     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
  115.       <dependentAssembly>
  116.         <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
  117.         <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
  118.       </dependentAssembly>
  119.       <dependentAssembly>
  120.         <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
  121.         <bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
  122.       </dependentAssembly>
  123.       <dependentAssembly>
  124.         <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
  125.         <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
  126.       </dependentAssembly>
  127.     </assemblyBinding>
  128.   </runtime>
  129.   <entityFramework>
  130.     <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
  131.       <parameters>
  132.         <parameter value="v11.0" />
  133.       </parameters>
  134.     </defaultConnectionFactory>
  135.   </entityFramework>
  136. </configuration>

代码上的全都配置好了,现在该是创建数据库的时候了,在安装Enterprise Library的时候,会提示你安装Source选择安装,安装完成之后,我们可以在里面找到数据库的sql文件。天屹在下面的目录里找到了数据库文件,C:\Users\Administrator\Documents\EntLib50Src\Blocks\Logging\Src\DatabaseTraceListener\Scripts\LoggingDatabase.sql,前面系统documents路径根据自己的机器各不相同,自己修改一下。

不知道什么原因,这个默认的数据库和我们的系统不兼容,两个存储过程有问题AddCategory和WriteLog,这两存储过程的参数和mvc内置的有一些出入,所以需要修改一下,下面列出修改的存储过程sql:

AddCategory

  1. USE [TYStudio_Logging]
  2. GO
  3. /****** Object:  StoredProcedure [dbo].[AddCategory]    Script Date: 04/06/2013 14:46:20 ******/
  4. SET ANSI_NULLS ON
  5. GO
  6. SET QUOTED_IDENTIFIER ON
  7. GO
  8. ALTER PROCEDURE [dbo].[AddCategory]
  9.     -- Add the parameters for the function here
  10.     @categoryName nvarchar(64),
  11.     @logID int
  12. AS
  13. BEGIN
  14.     SET NOCOUNT ON;
  15.     DECLARE @CatID INT
  16.     SELECT @CatID = CategoryID FROM Category WHERE CategoryName = @categoryName
  17.     IF @CatID IS NULL
  18.     BEGIN
  19.         INSERT INTO Category (CategoryName) VALUES(@categoryName)
  20.         SELECT @CatID = @@IDENTITY
  21.     END
  22.     EXEC InsertCategoryLog @CatID, @logID
  23.     RETURN @CatID
  24. END

 

WriteLog

  1. USE [TYStudio_Logging]
  2. GO
  3. /****** Object:  StoredProcedure [dbo].[WriteLog]    Script Date: 04/06/2013 14:48:27 ******/
  4. SET ANSI_NULLS ON
  5. GO
  6. SET QUOTED_IDENTIFIER ON
  7. GO
  8. /****** Object:  Stored Procedure dbo.WriteLog    Script Date: 10/1/2004 3:16:36 PM ******/
  9. ALTER PROCEDURE [dbo].[WriteLog]
  10. (
  11.     @eventID int,
  12.     @priority int,
  13.     @severity nvarchar(32),
  14.     @title nvarchar(256),
  15.     @timestamp datetime,
  16.     @machineName nvarchar(32),
  17.     @AppDomainName nvarchar(512),
  18.     @ProcessID nvarchar(256),
  19.     @ProcessName nvarchar(512),
  20.     @ThreadName nvarchar(512),
  21.     @Win32ThreadId nvarchar(128),
  22.     @message nvarchar(1500),
  23.     @formattedmessage ntext,
  24.     @LogId int OUTPUT
  25. )
  26. AS
  27.     INSERT INTO [Log] (
  28.         EventID,
  29.         Priority,
  30.         Severity,
  31.         Title,
  32.         [Timestamp],
  33.         MachineName,
  34.         AppDomainName,
  35.         ProcessID,
  36.         ProcessName,
  37.         ThreadName,
  38.         Win32ThreadId,
  39.         Message,
  40.         FormattedMessage
  41.     )
  42.     VALUES (
  43.         @eventID,
  44.         @priority,
  45.         @severity,
  46.         @title,
  47.         @timestamp,
  48.         @MachineName,
  49.         @AppDomainName,
  50.         @ProcessID,
  51.         @ProcessName,
  52.         @ThreadName,
  53.         @Win32ThreadId,
  54.         @message,
  55.         @formattedmessage)
  56.     SET @LogId = @@IDENTITY
  57.     RETURN @LogId

如果你先麻烦天屹的下篇文章会对整系统做一个总结,并且提供整个系统成型的源代码下载,系统的Commons工程里面会有Logging数据库的备份,你恢复一下也是可以的。

Logging数据库异常信息:

最后让我们来看一眼异常被记录到Logging数据库中的样子吧,这里面有详细的异常信息,还有我们自定义的异常信息,一目了然,当然Enterprise Library也提供出现异常发送邮件的功能,你只需要到Web.Config添加相应的配置就可以了,这样出现异常会第一时间发送到你指定的邮件。

exceptionmessaeg

到这里异常处日志记录处理就完成了。

下篇文章天屹将提供整个系统的代码下载,敬请期待。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多