服务器端捕捉asmx产生的未处理异常

项目中对于未处理异常的捕获是通过使用ApplicationErrorLog组件,但无论通过组件还是Global.asax或者自定义HttpModule都是通过在管道中截获异常信息,例如:
void Application_Error(object sender, EventArgs e)
{
    Logger.log(ex.Message);
    Logger.log(ex.StackTrace);
    
if (ex.InnerException != null)
    
{
        Logger.log(ex.InnerException.Message);
        Logger.log(ex.InnerException.StackTrace);
    }

}

但是通过管道这种方式是不能截获asmx调用过程中产生的未处理异常的,所以只能使用别的小技巧来解决这个问题。因为项目统一使用ApplicationErrorLog来捕获未处理异常的,所以这里就不好添加另类的方式,影响统一性。现在处理的方式是把asmx产生的异常post到一个ashx页面来接收这个异常,然后在该页面抛出,这样就可能通过正常的httpmodule来截获了。
1、封装post操作
    protected void PostEx(Exception ex)
    
{
        
string message = ex.ToJSON();

        
string postData = string.Format("Error={0}&id={1}", message, Guid.NewGuid());
        
byte[] data = Encoding.UTF8.GetBytes(postData);

        
string url = string.Format("http://{0}/Admin/AsmxException.ashx", ConfigurationManager.AppSettings["ProxyHost"]);
        HttpWebRequest request 
= (HttpWebRequest)HttpWebRequest.Create(url);
        request.Method 
= "POST";
        request.ContentType 
= "application/x-www-form-urlencoded";
        request.ContentLength 
= data.Length;
        request.Timeout 
= 500;

        
using (Stream requestStream = request.GetRequestStream())
        
{
            requestStream.Write(data, 
0, data.Length);
            requestStream.Close();
        }


        
try
        
{
            
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()){}
        }

        
catch (System.Net.WebException) { }
    }

2、新建ashx页面(AsmxException.ashx)来接收post过来的异常
public class AsmxException : IHttpHandler {
    
    
public void ProcessRequest (HttpContext context) {
        
string message = context.Request.Form["Error"];
        Exception ex 
= message.ParseJSON<Exception>();

        
throw ex;
    }

 
    
public bool IsReusable get return false; } }
}

3、在asmx中调用方法
    [WebMethod(MessageName = "UpdatingContent", Description = "", EnableSession = false)]
    [SoapHeader(
"Credentials")]
    
public void UpdatingContent(string identity)
    
{
        
try
        
{
            InnerValidate();

            
this.NotifyUpdating(Credentials.SourceID, Credentials.HandleMode, Credentials.CallbackProtocol,
                Credentials.UpdatingType, Credentials.INotifyHandlerImpl, identity);
        }

        
catch (Exception ex)
        
{
            PostEx(ex);
            
throw ex;
        }

    }

记得PostEx(ex)把发生的异常post到接收页面后还要再次抛出原来的异常,这样客户端才能正常收到原来的异常信息。
posted @ 2008-06-11 15:20  chenjunbiao  阅读(421)  评论(0编辑  收藏  举报