asp.net-mvc - txt - elmah教學




如何讓ELMAH使用ASP.NET MVC[HandleError]屬性? (6)

一個完全替代的解決方案是不使用MVC HandleErrorAttribute ,而是依賴於Elmah設計用於處理的ASP.Net錯誤處理。

您需要從App_Start \ FilterConfig(或Global.asax)中刪除默認的全局HandleErrorAttribute ,然後在您的Web.config中設置一個錯誤頁面:

<customErrors mode="RemoteOnly" defaultRedirect="~/error/" />

請注意,這可以是一個MVC路由URL,因此當發生錯誤時,上述內容將重定向到ErrorController.Index操作。

我試圖使用ELMAH在我的ASP.NET MVC應用程序中記錄錯誤,但是當我在我的控制器上使用[HandleError]屬性時,ELMAH在發生錯誤時不記錄任何錯誤。

正如我猜測它,因為ELMAH只記錄未處理的錯誤和[HandleError]屬性正在處理錯誤,因此不需要記錄它。

如何修改或如何修改屬性,ELMAH可以知道出現錯誤並記錄下來。

編輯:讓我確保每個人都明白,我知道我可以修改屬性那不是我問的問題...使用handleerror屬性時ELMAH被繞過,這意味著它不會看到有錯誤,因為它被處理已經通過屬性...我問的是有一種方法可以讓ELMAH看到錯誤並記錄它,即使該屬性處理它...我搜索周圍,並沒有看到任何方法調用來強制它記錄錯誤....


對不起,但我認為接受的答案是矯枉過正。 所有你需要做的是這樣的:

public class ElmahHandledErrorLoggerFilter : IExceptionFilter
{
    public void OnException (ExceptionContext context)
    {
        // Log only handled exceptions, because all other will be caught by ELMAH anyway.
        if (context.ExceptionHandled)
            ErrorSignal.FromCurrentContext().Raise(context.Exception);
    }
}

然後在Global.asax.cs中註冊它(順序很重要):

public static void RegisterGlobalFilters (GlobalFilterCollection filters)
{
    filters.Add(new ElmahHandledErrorLoggerFilter());
    filters.Add(new HandleErrorAttribute());
}

您可以通過引入一個自定義控制器工廠,將HandleErrorWithElmah屬性注入到每個控制器中,從而獲得上述代碼並進一步推進。

有關更多信息,請參閱我的博客系列文章,了解如何登錄MVC。 第一篇文章介紹讓Elmah成立並運行MVC。

文章末尾有一個可下載代碼的鏈接。 希望有所幫助。

http://dotnetdarren.wordpress.com/


我是ASP.NET MVC中的新成員。 我面臨同樣的問題,以下是我的Erorr.vbhtml中的可行性(如果您只需要使用Elmah日誌記錄錯誤,它就可以工作)

@ModelType System.Web.Mvc.HandleErrorInfo

    @Code
        ViewData("Title") = "Error"
        Dim item As HandleErrorInfo = CType(Model, HandleErrorInfo)
        //To log error with Elmah
        Elmah.ErrorLog.GetDefault(HttpContext.Current).Log(New Elmah.Error(Model.Exception, HttpContext.Current))
    End Code

<h2>
    Sorry, an error occurred while processing your request.<br />

    @item.ActionName<br />
    @item.ControllerName<br />
    @item.Exception.Message
</h2> 

簡單!


這正是我需要的MVC網站配置!

按照Atif Aziz的建議,我對OnException方法添加了一些修改來處理多個HandleErrorAttribute實例:

請記住,如果多個HandleErrorAttribute實例有效,則可能不得不注意,那麼重複日誌記錄不會發生。

我只需在調用基類之前檢查context.ExceptionHandled ,知道是否有其他人在當前處理程序之前處理了異常。
它適用於我,我發布代碼以防其他人需要它,並詢問是否有人知道我是否忽略了任何內容。

希望它是有用的:

public override void OnException(ExceptionContext context)
{
    bool exceptionHandledByPreviousHandler = context.ExceptionHandled;

    base.OnException(context);

    Exception e = context.Exception;
    if (exceptionHandledByPreviousHandler
        || !context.ExceptionHandled  // if unhandled, will be logged anyhow
        || RaiseErrorSignal(e)        // prefer signaling, if possible
        || IsFiltered(context))       // filtered?
        return;

    LogException(e);
}

您可以HandleErrorAttribute並覆蓋其OnException成員(無需複制),以便使用ELMAH記錄異常,並且僅在基本實現處理該異常時才執行該操作。 您需要的最少量的代碼如下所示:

using System.Web.Mvc;
using Elmah;

public class HandleErrorAttribute : System.Web.Mvc.HandleErrorAttribute
{
    public override void OnException(ExceptionContext context)
    {
        base.OnException(context);
        if (!context.ExceptionHandled) 
            return;
        var httpContext = context.HttpContext.ApplicationInstance.Context;
        var signal = ErrorSignal.FromContext(httpContext);
        signal.Raise(context.Exception, httpContext);
    }
}

首先調用基本實現,使其有機會將異常標記為正在處理。 只有這樣才能發出異常信號。 上述代碼很簡單,如果在HttpContext可能不可用的環境(如測試)中使用,則可能會導致問題。 因此,您需要更具防禦性的代碼(代價是略長一些):

using System.Web;
using System.Web.Mvc;
using Elmah;

public class HandleErrorAttribute : System.Web.Mvc.HandleErrorAttribute
{
    public override void OnException(ExceptionContext context)
    {
        base.OnException(context);
        if (!context.ExceptionHandled       // if unhandled, will be logged anyhow
            || TryRaiseErrorSignal(context) // prefer signaling, if possible
            || IsFiltered(context))         // filtered?
            return;

        LogException(context);
    }

    private static bool TryRaiseErrorSignal(ExceptionContext context)
    {
        var httpContext = GetHttpContextImpl(context.HttpContext);
        if (httpContext == null)
            return false;
        var signal = ErrorSignal.FromContext(httpContext);
        if (signal == null)
            return false;
        signal.Raise(context.Exception, httpContext);
        return true;
    }

    private static bool IsFiltered(ExceptionContext context)
    {
        var config = context.HttpContext.GetSection("elmah/errorFilter")
                        as ErrorFilterConfiguration;

        if (config == null)
            return false;

        var testContext = new ErrorFilterModule.AssertionHelperContext(
                              context.Exception, 
                              GetHttpContextImpl(context.HttpContext));
        return config.Assertion.Test(testContext);
    }

    private static void LogException(ExceptionContext context)
    {
        var httpContext = GetHttpContextImpl(context.HttpContext);
        var error = new Error(context.Exception, httpContext);
        ErrorLog.GetDefault(httpContext).Log(error);
    }

    private static HttpContext GetHttpContextImpl(HttpContextBase context)
    {
        return context.ApplicationInstance.Context;
    }
}

第二個版本將首先嘗試使用來自ELMAH的錯誤信號 ,這涉及到完全配置的管道,如日誌記錄,郵件發送,過濾和你有什麼。 否則,它會嘗試查看是否應該過濾錯誤。 如果不是,則只記錄錯誤。 此實現不處理郵件通知。 如果可以發出異常信號,則會發送一封郵件,如果配置為這樣的話。

如果多個HandleErrorAttribute實例有效,則可能還需要注意,重複日誌記錄不會發生,但上面的兩個示例應該會啟動。





elmah