• 探讨对Web控件的异常处理


    在使用ASP.NET时,常常使用Page的错误事件Error进行错误捕捉和处理。这种方式可以集中处理所有异常,这种方式有利有弊。集中处理的好处就不用啰嗦了,这里只说明一下这种方式的局限,就是当页面中的某个控件发生异常之后,整个页面执行都会中断,然后处理异常,这样一来,页面就无法显示。

    在实际开发中,常常有这样的需求,即页面是由多个相对独立的控件组成,其中一个控件的错误不能影响到其它控件的正常显示。这就需要在控件内部捕捉错误,并自行处理错误,然而控件基类并没有提供这样的错误捕捉功能。如何用简单有效方法来实现呢?

    其实我们可以实现一个基类,并把所有在控件生命期中会调用到的方法都封装起来,这样只要继承这个控件,就可以方便地实现在控件内部自行捕捉错误的功能。请看下面的代码:

      1public abstract class AbstractControl: Control
      2{
      3    /// <summary>
      4    /// 异常栈
      5    /// </summary> 

      6    public Stack Exceptions
      7    {
      8        get
      9        {
     10            if (exceptions == null)
     11            {
     12                exceptions = new Stack();
     13            }

     14            return exceptions;
     15        }

     16    }

     17
     18    protected override void CreateChildControls()
     19    {
     20        try
     21        {
     22            CreateChildControlsByCatchedException();
     23        }

     24        catch (HttpUnhandledException)
     25        {
     26            throw;
     27        }

     28        catch (Exception ex)
     29 408_436_Open_Image.style.display='inline'; Codehighlighter1_408_436_Open_Text.style.display='inline';" src="/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>        {
     30            Exceptions.Push(ex);
     31        }

     32    }

     33
     34    /// <summary>
     35    /// 创建子控件(已进行异常捕捉处理)
     36    /// </summary>

     37    protected virtual void CreateChildControlsByCatchedException()
     38    {
     39    }

     40
     41    /// <summary>
     42    /// 
     43    /// </summary>
     44    /// <param name="e"></param>

     45    protected override void OnPreRender(EventArgs e)
     46    {
     47        try
     48        {
     49            OnPreRenderByCatchedException(e);
     50        }

     51        catch (HttpUnhandledException)
     52        {
     53            throw;
     54        }

     55        catch (Exception ex)
     56        {
     57            Exceptions.Push(ex);
     58        }

     59    }

     60
     61    /// <summary>
     62    /// 呈现前事件(已进行错误捕捉处理)
     63    /// </summary>
     64    /// <param name="e"></param>

     65    protected virtual void OnPreRenderByCatchedException(EventArgs e)
     66    {
     67        base.OnPreRender (e);
     68    }

     69    
     70    /// <summary>
     71    /// 设计时的呈现前事件
     72    /// </summary>
     73    /// <param name="e"></param>

     74    protected virtual void DesigningOnPreRenderByCatchedException(EventArgs e)
     75    {
     76    }

     77
     78    /// <summary>
     79    /// 呈现
     80    /// </summary>
     81    /// <param name="writer"></param>

     82    protected override void Render(HtmlTextWriter writer)
     83    {
     84        if (Exceptions.Count > 0)
     85        {
     86            while (Exceptions.Count > 0 )
     87            {
     88                Exception ex = (Exception) Exceptions.Pop();
     89                RenderException(writer, ex);
     90            }

     91            return;
     92        }

     93        
     94        try
     95        {
     96            RenderByCatchedException(writer);
     97        }

     98        catch (HttpUnhandledException)
     99        {
    100            throw;
    101        }

    102        catch (Exception ex)
    103        {
    104            RenderException(writer, ex);
    105        }

    106    }

    107
    108    /// <summary>
    109    /// 呈现(已进行错误捕捉处理)
    110    /// </summary>
    111    /// <param name="writer"></param>

    112    protected virtual void RenderByCatchedException(HtmlTextWriter writer)
    113    {
    114        base.Render (writer);
    115    }

    116
    117    /// <summary>
    118    /// 呈现异常
    119    /// </summary>
    120    /// <param name="writer"></param>
    121    /// <param name="ex"></param>

    122    private void RenderException(HtmlTextWriter writer, Exception ex)
    123    {         
    124        writer.AddAttribute(HtmlTextWriterAttribute.Title, BuildExceptionInfomation(ex));
    125        writer.AddStyleAttribute("font-weight""700");
    126        writer.AddStyleAttribute("color""#f00");
    127        writer.AddStyleAttribute("border""1px solid #ddd");
    128        writer.AddStyleAttribute("cursor""pointer");
    129        writer.AddStyleAttribute("padding""0px 3px 0px 3px");
    130        writer.AddStyleAttribute("background-color""#ffe");
    131        writer.RenderBeginTag(HtmlTextWriterTag.Span);
    132        writer.Write("!");
    133        writer.RenderEndTag();
    134    }

    135
    136    /// <summary>
    137    /// 生成异常信息
    138    /// </summary>
    139    /// <param name="ex"></param>
    140    /// <returns></returns>

    141    private string BuildExceptionInfomation(Exception ex)
    142    {
    143        StringBuilder sb = new StringBuilder();
    144        sb.Append(ex.Message);
    145        sb.Append(Environment.NewLine);
    146        sb.Append(ex.GetType().FullName);
    147        sb.Append(Environment.NewLine);
    148        sb.Append(ex.StackTrace);
    149        return sb.ToString();
    150    }

    151    
    152    /// <summary>
    153    /// 中断程序的执行
    154    /// </summary>
    155    /// <param name="ex"></param>

    156    protected virtual void Interrupt(Exception ex)
    157    {
    158        throw new HttpUnhandledException(ex.Message, ex);
    159    }

    160}

    161

    上面的代码只重载了OnPreRender、Render和CreateChildControls三个方法,实际上还有OnInit、OnLoad等,可以视实际需要而重载,这样重载之后,所有错误都被捕捉,并存放在错误栈中,并在呈现时将错误以某种格式呈现在界面上。注意,继承AbstractControl基类的控件应重载如RenderByCatchedException之类的方法。

    如果某些错误不希望被捕捉,而是直接抛出到页面上,这时候还可以调用Interrupt方法来将错误直接抛出到页面上,并中断整个页面的执行。

  • 相关阅读:
    String类的substring方法
    postman绕过登录,进行接口测试的方法
    Dubbo
    那些吊炸天的互联网名词
    版本控制工具git
    Ubunto20.04 sudo apt-get update 出现目标被重置多次!
    ubuntu环境下搭建Hadoop集群中必须需要注意的问题
    Python作业---内置数据类型
    python作业完成简单的文件操作
    python3实现计算器
  • 原文地址:https://www.cnblogs.com/rrooyy/p/481419.html
Copyright © 2020-2023  润新知