【问题标题】:HttpNotFoundResult causes an HttpException to be thrown?HttpNotFoundResult 导致抛出 HttpException?
【发布时间】:2012-12-03 13:40:46
【问题描述】:

出于测试目的,我有这个方法:

public ActionResult Index()
{
    System.Diagnostics.Debug.Write("Index");
    return new HttpNotFoundResult();
}

正在调用该方法(输出“索引”)。不知何故,它导致HttpException 被抛出。在我的 Global.asax 文件中,我有一个 Application_Error 实现:

void Application_Error(object sender, EventArgs e)
{
    Exception exc = Server.GetLastError();
    if (exc is System.Web.HttpException)
    {
        string msg = "UrlReferrer: "
            + Context.Request.UrlReferrer + " UserAgent: " + Context.Request.UserAgent
            + " UserHostAddress: " + Context.Request.UserHostAddress + " UserHostName: "
            + Context.Request.UserHostName;

        ErrorHandler.Error(exc.Message, msg);
    }
    else {
        ...
    }
}

在系统处理完Index 的请求后调用此方法。我认为HttpNotFoundResult 会导致抛出异常 - 或者可能会为任何状态码为 404 的ActionResult 抛出异常。

这很烦人,因为它绕过了我的控制器上的OnException 处理程序。对于我的网站,Application_Error 应该是最后的后备方案 - 大多数正常错误都打算在其他地方处理(由控制器或操作过滤器)。我只希望Application_Error 记录完全意外的异常,或者记录图像或 .js 文件之类的 404。

有没有办法阻止 asp.net 为程序生成的 404 引发异常?或者,有没有办法在Application_Error 中确定HttpException 是否由程序生成的 404 引起?

【问题讨论】:

    标签: c# asp.net asp.net-mvc


    【解决方案1】:

    您可以创建一个自定义异常过滤器来处理所有操作引发的 404 异常。您可以使用 HttpContext.Items 集合来跟踪它是否是程序引发的 404。

    自定义异常过滤器

    public class NotFoundExceptionFilter : IExceptionFilter
    {        
        public void OnException(ExceptionContext filterContext)
        {
            // ignore if the exception is already handled or not a 404
            if (filterContext.ExceptionHandled || new HttpException(null, filterContext.Exception).GetHttpCode() != 404)
                return;
    
            filterContext.HttpContext.Items.Add("Programmatic404", true);
            filterContext.ExceptionHandled = true;
        }
    }
    

    您需要将NotFoundExceptionFilter 应用为全局过滤器。

    Application_Error 事件

    public static void Application_Error(object sender, EventArgs e)
    {
        var httpContext = ((MvcApplication)sender).Context;
    
        // ignore if it is a programatically raised 404
        if(httpContext.Items["Programmatic404"] != null && bool.Parse(httpContext.Items["Programmatic404"].ToString()))
            return;
    
        // else, Log the exception
    }
    

    【讨论】:

    • 这是一个非常巧妙的想法,它实际上解决了我的另一个问题。但是,asp.net 引发的HttpException 没有到达异常过滤器。似乎异常是从控制器外部引发的。因此,此解决方案在这里不起作用。
    • @Oliver 你所说的异常是什么意思是在控制器之外抛出的?我想你知道内置的 HandleError 不处理 500 以外的 http 异常。
    • 我认为,在 asp.net 堆栈中的某个位置,某些东西会检查响应的状态代码是否为 404,如果是这种情况则抛出 HttpException。我认为这必须在控制器被消耗和丢弃后发生,因为OnException 事件不会为它触发。所以在这里,您的异常过滤器似乎没有检测到HttpException,因为它的OnException 方法没有被调用。但是,它会检测到从 action 方法内部手动抛出的 HttpException。
    猜你喜欢
    • 2011-07-28
    • 1970-01-01
    • 2015-12-12
    • 2016-03-15
    • 1970-01-01
    • 2022-08-03
    • 1970-01-01
    • 2020-05-10
    • 1970-01-01
    相关资源
    最近更新 更多