asp.net / MOSS2007的透明通用异常处理(带代码)

时间:2008-11-11 09:23:55

标签: asp.net sharepoint exception-handling moss

这不是一个问题,但是我希望可以帮助一些人的事情......

前段时间,我编写了一个通用的透明异常处理模块,用于MOSS 2007(Sharepoint)解决方案。该解决方案有许多Web部件,Web部件经常会断开,导致它们所在的整个页面崩溃。这导致我们的测试人员无法忍受痛苦,因为他们无法轻易看到页面的哪个部分导致崩溃,也无法在Web部件修复之前继续测试。通常情况下,崩溃的Web部件甚至与测试人员无关,但仍然使他们无法完成工作。显然需要做点什么。

你可能会争辩说,最好的解决方案就是扣上并修复dang web部件..但是它们中有很多,并且负责混乱的编码器已经移动(听起来很熟悉?)所以我们有为部件使用通用的通用异常处理策略的想法。

我们希望在Web部件或Web控件等中崩溃,不要使整个页面崩溃,而是在开发过程中在网页中内联输出堆栈跟踪,并获得友好的消息(由webparts本身定义,或者标准消息)在运行时输出给用户,而不是整个页面。

当时我们不知道任何此类解决方案。 (我还是没有)。 我认为,最好的方法是将我所做的(包含文件)包含在ASP.Net框架中。 (如果你们ASP.Net的任何人都在读这个:随意窃取我的代码。它会更好地工作在类层次结构中越高 例如,它可以是System.Web.UI.WebControls.WebControl的一部分,有一些web.config设置你可以调整来激活它...它会在开发过程中帮助堆积..至少它会帮助我:))

所以,对于我们结束的解决方案: 我创建了一个BaseWebPart,其中所有其他Web部件(间歇性崩溃的部分)将继承。从继承之后,BaseWebPart将确保try / catch包含来自ASP.Net框架(Render,CreateChildControls等等)的所有调用,以便在其中一个中发生崩溃得到很好的处理。 然后,每个Web部件都可以覆盖一个名为HandleException的方法,以控制崩溃时发生的情况。默认行为(如果他们没有覆盖)设置为

在调试模式下渲染堆栈跟踪 要么 在处于发布模式时呈现标准错误消息

为了用异常处理包装每个框架调用, 我们有一个双层方法,其中

     
  1. 第一层(ExceptionHandlingWebPartBase)覆盖并密封方法,
  2.  
  3. 然后将try / catch应用于一组新的方法,转发方法参数
  4.  
  5. 在第二层(BaseWebPart)
  6. 中覆盖了这些新方法  
  7. 密封它们并调用与框架方法命名相同的新虚拟方法。
  8.  
  9. 然后根据需要在继承自BaseWebPart的常规Web部件中覆盖这些方法(现在使用它们周围的catch块)。因此,异常处理对继承者是透明的。
  10. 这个模块唯一的缺点是MOSS有几个“基础”Web部件,你可以继承自己的Web部件,所以这个BaseWebPart必须为每个部分重复一次。 我们还希望在Web控件上使用此功能, 所以我们必须基本上复制代码来制作BaseWebControl。 如果此错误处理模块包含在层次结构中较高的位置(例如WebControl或Control中),则一次就足以涵盖所有不同的情况。不幸的是,c#不允许使用mixins,或者我们可能一下子就可以完全应用异常处理。目前,发现4-5类重复的相同代码更适合40-50个具有重复异常处理逻辑的类。

    “它有效吗?”你问?以及从这种设置中获得的好处包括

       
    1. 在测试期间无需紧急修补程序测试环境
    2.  
    3. 保证在生产中记录例外
    4.  
    5. 来自测试人员的一般更清醒的错误分类(在他们只是说“每次都关闭,此页面不起作用 - 这是不可接受的,1级错误”之前
    6.  
    7. 网页部分中的一些例外情况进入生产阶段,但不是导致整个页面停止,而是显示了一条友好的消息,为我们购买了大量的时间来修复问题(下一个版本而不是修补程序)
    8. 下次我在一个包含大量网页部件,网页控件或自定义控件的项目中时,我肯定会再次使用此设置。

      等等,代码:

      using System;
      using System.IO;
      using System.Text;
      using System.Web.UI;
      using System.Web.UI.WebControls.WebParts;
      
      ///*'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      /// This is the work of Andreas Knudsen (andreas.knudsen [ at ] gmail.com)
      /// Anyone may use this work freely as it stands, or change it to suit their needs
      /// on one condition: All use is on your own risk. It works for me, but I will not be
      /// liable for any losses incurred by the use of this work. 
      /// 
      /// If you would hold me responsible, you are not to use this work.
      /// ************************************************************************************
      /// 
      /// In order to be truly useful, customizations are needed on lines 120 and 130
      /// (search for CUSTOMIZE HERE! 
      /// 
      /// ************************************************************************************
      namespace Util
      {
      /// <summary> 
      /// Base class for web part development. 
      /// All web parts should inherit from this class. 
      /// Exceptions thrown from web parts inheriting from this base 
      /// will not crash the Page the web part is on, but rather do one of two things:
      /// 
      /// 1)If compiled in debug mode: Render the stacktrace of the exception inline in the web page
      /// 2)If compiled in release mode: Render a friendly error message inline in the web page.
      /// 
      /// This behaviour can be overridden by inheritors by overriding the method HandleException
      ///  
      /// HOW THIS WORKS:
      /// -------
      /// In order to wrap each framework call with exception handling, 
      /// we have a two-tiered approach in which 
      /// 1) the first tier (ExceptionHandlingWebPartBase) overrides and seals methods, 
      /// 2) then applies try/catch to a new set of methods, forwarding method parameters
      /// 3) these new methods are overridden in the second tier (BaseWebPart)
      /// 4) where they are sealed and a call is made to new virtual methods that are named the 
      /// same as the framework methods.
      /// 5) These methods (now with a catch-block around them) are then overridden as needed in a 
      /// regular web part that inherits from BaseWebPart. The exception handling is thus 
      /// transparent to the inheritor.
      /// </summary>
      public abstract class BaseWebPart : ExceptionHandlingWebPartBase
      {
        #region temp methods for method piping (overrides and seals methods from ExceptionHandlingWebPartBase)
        /*
               * These methods re part of the plumbing necessary to give inheritors
               * the expected interface.
               */
        public override sealed void RenderWebPart(HtmlTextWriter writer)
        {
            Render(writer);
        }
      
        public override sealed void CreateWebPartChildControls()
        {
            CreateChildControls();
        }
      
        public override sealed void InitWebPart(EventArgs e)
        {
            OnInit(e);
        }
      
        public sealed override void PreRenderWebPart(EventArgs e)
        {
            OnPreRender(e);
        }
      
        public sealed override void LoadWebPart(EventArgs e)
        {
            OnLoad(e);
        }
        #endregion
        #region Methods in which exceptions are now handled.
        protected new virtual void Render(HtmlTextWriter writer)
        {
            base.RenderWebPart(writer);
        }
        protected new virtual void CreateChildControls()
        {
            base.CreateWebPartChildControls();
        }
      
        protected new virtual void OnInit(EventArgs e)
        {
            base.InitWebPart(e);
        }
      
        protected new virtual void OnLoad(EventArgs e)
        {
            base.LoadWebPart(e);
        }
      
        protected new virtual void OnPreRender(EventArgs e)
        {
            base.PreRenderWebPart(e);
        }
        #endregion
      }
      
      
      public abstract class ExceptionHandlingWebPartBase : WebPart
      {
      
        #region Exception handling section
        private StringBuilder _errorOutput;
        private bool _abortProcessing;
        public virtual bool AbortProcessing
        {
            get { return _abortProcessing; }
            set { _abortProcessing = value; }
        }
      
        public virtual void HandleException(Exception e, HtmlTextWriter writer)
        {
      #if !DEBUG
           // CUSTOMIZE HERE! 
            writer.Write("TODO: Insert helpful error message here");
      #else
            writer.Write(e.Message + "<br/>" + e.StackTrace);
      #endif
      
        }
      
        public void ExceptionHappened(Exception ex)
        {
            AbortProcessing = true;
            //CUSTOMIZE HERE!
            //TODO: use own logging framework here:
            //Logger.Log(Severity.Error, ex.Message + " " + ex.StackTrace);
      
            HandleException(ex, new HtmlTextWriter(new StringWriter(_errorOutput)));
        }
      
        #endregion
      
        #region Override framework methods for method piping
        protected override sealed void CreateChildControls()
        {
      
            if (!AbortProcessing)
            {
                try
                {
                    CreateWebPartChildControls();
                }
                catch (Exception e)
                {
                    ExceptionHappened(e);
                }
            }
        }
      
        protected override sealed void OnInit(EventArgs e)
        {
            AbortProcessing = false;
      
            _errorOutput = new StringBuilder();
      
            try
            {
                InitWebPart(e);
            }
            catch (Exception ex)
            {
                ExceptionHappened(ex);
            }
        }
        protected override sealed void Render(HtmlTextWriter writer)
        {
            StringBuilder tempOutput = new StringBuilder();
            if (!AbortProcessing)
            {
                HtmlTextWriter tempWriter = new HtmlTextWriter(new StringWriter(tempOutput));
      
                try
                {
                    RenderWebPart(tempWriter);
                }
                catch (Exception ex)
                {
                    ExceptionHappened(ex);
                }
            }
            if (AbortProcessing)
            {
                writer.Write(_errorOutput.ToString());
            }
            else
            {
                writer.Write(tempOutput.ToString());
            }
        }
        protected override sealed void OnLoad(EventArgs e)
        {
            if (!AbortProcessing)
            {
                try
                {
                    LoadWebPart(e);
                }
                catch (Exception ex)
                {
                    ExceptionHappened(ex);
                }
      
      
            }
        }
        protected override sealed void OnPreRender(EventArgs e)
        {
            if (!AbortProcessing)
            {
                try
                {
                    PreRenderWebPart(e);
                }
                catch (Exception ex)
                {
                    ExceptionHappened(ex);
                }
      
            }
        }
        #endregion
      
        #region Temp methods for method piping (will be overridden and sealed in subclass)
        public virtual void RenderWebPart(HtmlTextWriter writer)
        {
            EnsureChildControls();
            base.Render(writer);
        }
        public virtual void CreateWebPartChildControls()
        {
            base.CreateChildControls();
        }
        public virtual void InitWebPart(EventArgs e)
        {
            base.OnInit(e);
        }
        public virtual void LoadWebPart(EventArgs e)
        {
            base.OnLoad(e);
        }
        public virtual void PreRenderWebPart(EventArgs e)
        {
            base.OnPreRender(e);
        }
        #endregion
      }
      }
      

0 个答案:

没有答案