簡體   English   中英

Controller中的異常處理(ASP.NET MVC)

[英]Exception handling in Controller (ASP.NET MVC)

當您從控制器中的操作調用的自己的代碼拋出異常時應該如何處理? 我看到很多最佳實踐的例子,其中根本沒有try-catch語句。 例如,從存儲庫訪問數據:

public ViewResult Index()
{
    IList<CustomModel> customModels = _customModelRepository.GetAll();
    return View(customModels);
}

顯然,如果調用它是一個無法訪問的數據庫,並且我們正在使用像Entity Framework這樣的ORM,則此代碼可能會拋出異常。

但是,我能看到的所有事情都會發生異常,並且會向用戶顯示一條令人討厭的錯誤消息。

我知道HandleError屬性,但據我所知,如果發生未處理的異常,它主要用於將您重定向到錯誤頁面。

當然,這段代碼可以包裝在try-catch中,但不能很好地分離,特別是如果你有更多的邏輯:

public ViewResult Index()
{
    if (ValidationCheck())
    {
        IList<CustomModel> customModels = new List<CustomModel>();
        try
        {
            customModels = _customModelRepository.GetAll();
        }
        catch (SqlException ex)
        {
            // Handle exception
        }

        if (CustomModelsAreValid(customModels))
            // Do something
        else
            // Do something else
    }

    return View();
}

以前我已經提取出所有可以將數據庫調用之類的異常拋出到DataProvider類中的代碼,該類處理錯誤並返回消息以向用戶顯示消息。

我想知道處理這個問題的最佳方法是什么? 我並不總是希望返回錯誤頁面,因為一些例外不應該這樣做。 相反,應該以正常視圖顯示給用戶的錯誤消息。 我以前的方法是正確的還是有更好的解決方案?

我做了三件事來顯示更多用戶友好的消息:

  1. 利用全局異常處理程序。 對於MVC:Global.asax中的Application_Error。 在這里學習如何使用它: http//msdn.microsoft.com/en-us/library/24395wz3(v = vs.100).aspx
  2. 我將Exception子類化為UserFriendlyException。 我盡我所能在我的所有底層服務類中拋出這個UserFriendlyException而不是一個普通的舊Exception。 我總是嘗試將用戶有意義的消息放在這些自定義異常中。 其主要目的是能夠對Application_Error方法中的異常進行類型檢查。 對於UserFriendlyExceptions,我只使用我在服務中深入設置的用戶友好消息,例如“嘿!91度不是有效的緯度值!”。 如果它是一個常規異常,那么有些情況我沒有處理,所以我顯示了一個更通用的錯誤消息,如“哎呀,出錯了!我們會盡力解決這個問題!”。
  3. 我還創建了一個ErrorController,負責呈現用戶友好的視圖或JSON。 這是控制器,其方法將從Application_Error方法調用。

編輯:我想我會提到ASP.NET Web API,因為它密切相關。 因為Web API端點的使用者不一定是瀏覽器,所以我喜歡稍微處理錯誤。 我仍然使用“FriendlyException”(上面的#2),但不是重定向到ErrorController,而是讓我的所有端點返回某種包含Error屬性的基類型。 因此,如果異常一直到Web API控制器,我確保將該錯誤粘貼在API響應的Error屬性中。 此錯誤消息將是從API控制器所依賴的類中冒出的友好消息,或者如果異常類型不是FriendlyException,則它將是通用消息。 這樣,消費客戶端可以簡單地檢查API響應的Error屬性是否為空。 如果錯誤存在則顯示消息,否則照常進行。 好消息是,由於友好的消息概念,消息對於用戶而言可能比通用的“錯誤!”更有意義。 信息。 我在使用Xamarin編寫移動應用程序時使用此策略,我可以在我的Web服務和iOS / Android應用程序之間共享我的C#類型。

使用Asp.Net MVC,您還可以為您的控制器覆蓋OnException方法。

protected override void OnException(ExceptionContext filterContext)
{
    if (filterContext.ExceptionHandled)
    {
        return;
    }
    filterContext.Result = new ViewResult
    {
        ViewName = ...
    };
    filterContext.ExceptionHandled = true;
}

這允許您重定向到自定義錯誤頁面,如果您願意,可以使用引用該異常的消息。

我使用了OnException覆蓋,因為我有幾個項目引用到一個具有處理錯誤的Controller的項目:

安全/ HandleErrorsController.cs

protected override void OnException(ExceptionContext filterContext) 
{
    MyLogger.Error(filterContext.Exception);   //method for log in EventViewer

    if (filterContext.ExceptionHandled)
        return;

    filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;

    filterContext.Result = new JsonResult
    {
        Data = new
        {
            Success = false, 
            Error = "Please report to admin.",
            ErrorText = filterContext.Exception.Message,
            Stack = filterContext.Exception.StackTrace
        },
        JsonRequestBehavior = JsonRequestBehavior.AllowGet
    };
    filterContext.ExceptionHandled = true;
}

像這樣的所有問題都不是很有建設性,因為答案總是“它取決於”,因為有很多方法可以處理錯誤處理。

許多人喜歡使用HandleError方法,因為任何異常基本上都是不可恢復的。 我的意思是,如果你不能歸還物體,你打算做什么? 無論如何你會向他們展示一個錯誤,對吧?

問題變成了,你想如何向他們展示錯誤。 如果顯示錯誤頁面是可以接受的,那么HandleError工作正常,並提供了一個記錄錯誤的簡單位置。 如果您正在使用Ajax或想要更高級的東西,那么您需要開發一種方法來實現這一點。

您談論DataProvider類。 這基本上就是你的存儲庫。 為什么不將它構建到您的存儲庫中?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM