Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/visual-studio-code/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 3 当customerrors=”时,应用程序“错误未触发”;关于;_Asp.net Mvc 3_Application Error - Fatal编程技术网

Asp.net mvc 3 当customerrors=”时,应用程序“错误未触发”;关于;

Asp.net mvc 3 当customerrors=”时,应用程序“错误未触发”;关于;,asp.net-mvc-3,application-error,Asp.net Mvc 3,Application Error,我在global.asax文件的Application\u Error事件中有代码,该事件在发生错误时执行,并通过电子邮件将错误的详细信息发送给我自己 void Application_Error(object sender, EventArgs e) { var error = Server.GetLastError(); if (error.Message != "Not Found") { // Send email here... }

我在
global.asax
文件的
Application\u Error
事件中有代码,该事件在发生错误时执行,并通过电子邮件将错误的详细信息发送给我自己

void Application_Error(object sender, EventArgs e)
{
    var error = Server.GetLastError();

    if (error.Message != "Not Found")
    {
        // Send email here...
    }

}
当我在VisualStudio中运行它时,它工作得很好,但是当我发布到我们的实时服务器时,
Application\u Error
事件不会触发

在一些测试之后,我可以在设置
customErrors=“Off”
时触发
应用程序错误,但是将其设置回
customErrors=“On”
会阻止事件再次触发


有人能告诉我为什么在
web.config
中启用
customErrors
Application\u Error
不会触发吗?

据我所知,您正在将控制权传递给url参数中指定的页面,并且您的事件通知将位于此处,而不是Application\u Error

<customErrors defaultRedirect="myErrorPage.aspx"
              mode="On">
</customErrors>


在这里可以找到很多信息:

为了解决这个问题,我最终禁用了customerrors,并在global.asax中处理来自应用程序错误事件的所有错误。MVC有点棘手,因为我不想返回301重定向,我想返回合适的错误代码。更多细节可以在我的博客上查看,但最终代码如下所示

void Application_Error(object sender, EventArgs e)
{
    var error = Server.GetLastError();
    var code = (error is HttpException) ? (error as HttpException).GetHttpCode() : 500;

    if (code != 404)
    {
            // Generate email with error details and send to administrator
    }

    Response.Clear();
    Server.ClearError();

    string path = Request.Path;
    Context.RewritePath(string.Format("~/Errors/Http{0}", code), false);
    IHttpHandler httpHandler = new MvcHttpHandler();
    httpHandler.ProcessRequest(Context);
    Context.RewritePath(path, false);
}
这是控制器

public class ErrorsController : Controller
{

    [HttpGet]
    public ActionResult Http404(string source)
    {
            Response.StatusCode = 404;
            return View();
    }

    [HttpGet]
    public ActionResult Http500(string source)
    {
            Response.StatusCode = 500;
            return View();
    }

}

更新
因为这个答案确实提供了一个解决方案,所以我不会对它进行编辑,但我找到了一个更干净的方法来解决这个问题。有关详细信息,请参阅

原始答案:
我弄明白了为什么没有调用
Application\u Error()
方法

Global.asax.cs

public class MvcApplication : System.Web.HttpApplication
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute()); // this line is the culprit
    }
...
}
默认情况下(生成新项目时),MVC应用程序在
Global.asax.cs
文件中有一些逻辑。此逻辑用于映射路由和注册筛选器。默认情况下,它只注册一个过滤器:一个
HandleErrorAttribute
过滤器。当customErrors处于启用状态时(或通过远程请求,当它设置为RemoteOnly时),HandleErrorAttribute告诉MVC查找错误视图,并且它从不调用
应用程序\u Error()
方法。我找不到这方面的文档,但在中进行了解释

要获取为每个未处理的异常调用的ApplicationError()方法,只需删除注册HandleErrorAttribute筛选器的行

现在的问题是:如何配置customErrors以获得您想要的

customErrors部分默认为
redirectMode=“ResponseRedirect”
。您也可以将defaultRedirect属性指定为MVC路由。我创建了一个非常简单的ErrorController,并将我的web.config更改为如下所示

<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite" defaultRedirect="~/Error.aspx">
  <error statusCode="404" redirect="~/PageNotFound.aspx" />
</customErrors>
web.config

<customErrors mode="RemoteOnly" redirectMode="ResponseRedirect" defaultRedirect="~/Error">
  <error statusCode="404" redirect="~/Error/PageNotFound" />
</customErrors>
此块告诉要使用正确的状态代码服务的页面。当然,在PageNotFound.aspx页面上,我使用了
HttpStatusCode.NotFound
。我将我的web.config更改为如下所示

<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite" defaultRedirect="~/Error.aspx">
  <error statusCode="404" redirect="~/PageNotFound.aspx" />
</customErrors>

一切都很好

摘要:

  • 删除以下行:
    filters.Add(新HandleErrorAttribute())
  • 使用
    Application\u Error()
    方法记录异常
  • 将customErrors与ResponseWrite一起使用,指向ASPX页面
  • 让ASPX页面负责自己的响应状态代码
我注意到这个解决方案有几个缺点

  • ASPX页面不能与Razor模板共享任何标记,我必须重写我们网站的标准页眉和页脚标记,以获得一致的外观和感觉
  • *.aspx页面可以通过点击其URL直接访问
这些问题有解决的办法,但我对它们关注不够,没有做任何额外的工作


我希望这对每个人都有帮助

我通过创建一个ExceptionFilter并在那里记录错误而不是应用程序错误来解决这个问题。您只需在RegisterGlobalFilters中添加对in的调用

log4netExceptionFilter.cs

using System
using System.Web.Mvc;

public class log4netExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext context)
    {
        Exception ex = context.Exception;
        if (!(ex is HttpException)) //ignore "file not found"
        {
            //Log error here
        }
    }
}
Global.asax.cs

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new log4netExceptionFilter()); //must be before HandleErrorAttribute
    filters.Add(new HandleErrorAttribute());
}

我喜欢Mark对ExceptionFilter的回答,但是如果您的所有控制器都派生自同一个基本控制器,那么另一个选择是简单地重写基本控制器中的一个异常。您可以在那里进行日志记录和发送电子邮件。这样做的好处是,可以使用IoC容器中已注入基本控制器的任何依赖项

您仍然可以将IoC与IEExceptionFilter一起使用,但配置绑定有点棘手。

我发现了一种更简洁的方法,它描述了在MVC3 web应用中创建自定义错误页的方法,该方法不阻止记录异常

解决方案是使用
部分的元素

我像这样配置了我的Web.config

<httpErrors errorMode="DetailedLocalOnly" existingResponse="Replace">
  <remove statusCode="404" subStatusCode="-1" />
  <remove statusCode="500" subStatusCode="-1" />
  <error statusCode="404" path="/Error/NotFound" responseMode="ExecuteURL" />
  <error statusCode="500" path="/Error" responseMode="ExecuteURL" />
</httpErrors>
视图非常简单,我只是使用标准的Razor语法来创建页面

仅此一点就足以让您在MVC中使用自定义错误页面

我还需要记录异常,所以我偷了使用自定义ExceptionFilter的机会

public class ExceptionPublisherExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext exceptionContext)
    {
        var exception = exceptionContext.Exception;
        var request = exceptionContext.HttpContext.Request;
        // log stuff
    }
}
最后需要在Global.asax.cs文件中注册异常过滤器:


这感觉像是一个比我以前的答案更干净的解决方案,而且就我所知效果也一样好。我特别喜欢它,因为我不觉得我在与MVC框架抗争;这个解决方案实际上利用了它

这篇博客文章帮助了我:

如果您使用的是IIS 7.0或更高版本,则可以更改Web.config文件以处理过大的请求。有一些警告,但这里有一个例子:

<system.webServer>
  <security>
    <requestFiltering>
      <requestLimits maxAllowedContentLength="1048576" />
    </requestFiltering>
  </security>
  <httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="404" subStatusCode="13" />
    <error statusCode="404" subStatusCode="13" prefixLanguageFilePath="" path="/UploadTooLarge.htm" responseMode="Redirect" />
  </httpErrors>
</system.webServer>
还请注意,当
响应模式
重定向
时,
路径
属性必须是绝对路径,因此,如果相关,请在虚拟目录名称之前加上前缀。Jesse Webb的信息性回答展示了如何使用
responseMode实现这一点
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new ExceptionPublisherExceptionFilter());
    filters.Add(new HandleErrorAttribute());
}
<system.webServer>
  <security>
    <requestFiltering>
      <requestLimits maxAllowedContentLength="1048576" />
    </requestFiltering>
  </security>
  <httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="404" subStatusCode="13" />
    <error statusCode="404" subStatusCode="13" prefixLanguageFilePath="" path="/UploadTooLarge.htm" responseMode="Redirect" />
  </httpErrors>
</system.webServer>
<system.web>
  <httpRuntime maxRequestLength="10240" />
</system.web>
public class ExceptionPublisherExceptionFilter : IExceptionFilter
    {
        private static Logger _logger = LogManager.GetCurrentClassLogger();
        public void OnException(ExceptionContext exceptionContext)
        {
            var exception = exceptionContext.Exception;
            var request = exceptionContext.HttpContext.Request;
            // HttpException httpException = exception as HttpException;
            // Log this exception with your logger
            _logger.Error(exception.Message);
        }
    }