[ASP.NET MVC] Global Error Handler - 實作 HandleErrorAttribute 捕捉應用程式例外並紀錄請求參數 by AjaxRequest

上一篇 [ASP.NET MVC] 自訂Global ErrorHandler 紀錄請求參數 沒有處理到 Ajax,這篇繼續補完...

開發環境

  • VS 2017
  • .NET Framework 4.7.2
  • .NLog 4.6.3

 

若對 ErrorHandler 使用方式不熟悉的,請參考

https://shiyousan.com/post/635838881238204198

沿用上一篇的範例

https://dotblogs.com.tw/yc421206/2019/05/16/asp_mvc_global_exception_handler_log_request_variable
 

實作

GlobalHandleErrorAttribute 做了兩件事

  1. 加上 filterContext.HttpContext.Request.IsAjaxRequest() 的判斷
  2. 由於調用端可能是來自別人寫的前端,為了例外保護訊息,IsDebuggingEnabled 判斷是否呈現例外的設定,就不像上一篇那樣放在 cshtml,而是直接在後端處理完
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
    dynamic data;
    if (filterContext.HttpContext.IsDebuggingEnabled)
    {
        data = new
        {
            filterContext.Exception.Message,
            filterContext.Exception.StackTrace,
            RequestVariable = request
        };
    }
    else
    {
        data = new
        {
            Message = "An unexpected error has occurred. Please contact the system administrator."
        };
    }
 
    filterContext.Result = new JsonResult
    {
        JsonRequestBehavior = JsonRequestBehavior.AllowGet,
        Data                = data
    };
}

 

HomeController 新增加一個 Action,模擬例外,我註解的扣可以解開觀察一下他的效果

[HttpGet]
public ActionResult Query(string id)
{
    var employee = new Employee
    {
        Id   = Guid.NewGuid(),
        Name = "yao",
        Age  = 19
    };
    InstanceUtility.HttpRequestState.SetCurrentVariable(employee);
 
    if (string.IsNullOrEmpty(id))
    {
        throw new Exception("壞掉了");
 
        //return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Id not be empty");
        //return this.HttpNotFound();
 
        //return this.Json(new
        //                 {
        //                     Id           = id,
        //                     Success      = false,
        //                     ErrorMessage = "Id not be empty"
        //                 },
        //                 JsonRequestBehavior.AllowGet);
    }
 
    return this.Json(new {Success = true, Id = id}, JsonRequestBehavior.AllowGet);
}

 

在 Index.cshtml 打 Query Action

@section Scripts
{
    <script type="text/javascript">
        var url = '@Html.Raw(Url.Action("Query", "Home"))';
 
        $.ajax({
            url: url,
            type: 'Get',
            contentType: "application/json;charset=utf-8",
            success: function(request, status, data) {
                if (data.Success) {
                    alert('OK!!!');
                } else {
                    alert('Oops..' + data.statusText);
                }
            },
            error: function(xhr, status, error) {
                console.log("statusText:" + xhr.statusText); //ErrorMessage
                console.log("responseText:" + xhr.responseText); //StackTrace (if debug or overridden)
                console.log("status:" + xhr.status); //Numeric status code
                var errorMessage = "";
                if (xhr.status === 500) {
                    var exception = JSON.parse(xhr.responseText);
                    errorMessage = "error:" + exception.Message + ",request:" +JSON.stringify( exception.RequestVariable) ;
                } else {
                    errorMessage = error;
                }
                alert(errorMessage);
            }
 
        });
    </script>
}

 

執行結果

訊息好像太多了,需要再依需求修改

 

到目前為止這個 Handler 就能同時處理Ajax、cshtml,有需要的話再來調整

 

如果,你想要使用文本,可以使用 ContentResult

var content = filterContext.HttpContext.IsDebuggingEnabled
                  ? filterContext.Exception.StackTrace
                  : "An unexpected error has occurred. Please contact the system administrator.";
 
filterContext.Result = new ContentResult
{
    ContentType = "text/plain",
    Content     = content
};
 
filterContext.HttpContext.Response.Status = "500 " +
                                            filterContext.Exception.Message
                                                         .Replace("\r", " ")
                                                         .Replace("\n", " ");

 

還有更多的 ActionResult....

專案路徑

https://github.com/yaochangyu/sample.dotblog/tree/master/MVC5/ErrorHandlers

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo