Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/15.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.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 ASP.NET MVC中的错误处理_Asp.net Mvc_Exception - Fatal编程技术网

Asp.net mvc ASP.NET MVC中的错误处理

Asp.net mvc ASP.NET MVC中的错误处理,asp.net-mvc,exception,Asp.net Mvc,Exception,如何正确处理ASP.NET MVC中控制器引发的异常?HandleError属性似乎只处理MVC基础设施引发的异常,而不是我自己的代码引发的异常 使用此web.config <customErrors mode="On"> <error statusCode="401" redirect="/Errors/Http401" /> </customErrors> 没有得到我所希望的结果。相反,我会得到一个通用的ASP.NET错误页面,告诉我修改web.

如何正确处理ASP.NET MVC中控制器引发的异常?
HandleError
属性似乎只处理MVC基础设施引发的异常,而不是我自己的代码引发的异常

使用此web.config

<customErrors mode="On">
    <error statusCode="401" redirect="/Errors/Http401" />
</customErrors>
没有得到我所希望的结果。相反,我会得到一个通用的ASP.NET错误页面,告诉我修改web.config以查看实际的错误信息。但是,如果不是引发异常,而是返回无效视图,则会得到/Shared/Views/Error.aspx页面:

return View("DoesNotExist");
在控制器中抛出异常,就像我在上面所做的那样,似乎绕过了所有的
HandleError
功能,那么创建错误页面的正确方法是什么?如何更好地使用MVC基础设施

HandleError属性似乎只处理MVC基础设施引发的异常,而不是我自己的代码引发的异常

这是错误的。事实上,HandleError只会“处理”您自己的代码或您自己的代码调用的代码中抛出的异常。换句话说,只有您的操作在调用堆栈中的异常才会出现

你看到的行为的真正解释是你抛出的特定异常。HandleError与HttpException的行为不同。从源代码:

        // If this is not an HTTP 500 (for example, if somebody throws an HTTP 404 from an action method),
        // ignore it.
        if (new HttpException(null, exception).GetHttpCode() != 500) {
            return;
        }

Controller.OnException(ExceptionContext上下文)
。覆盖它

protected override void OnException(ExceptionContext filterContext)
{
    // Bail if we can't do anything; app will crash.
    if (filterContext == null)
        return;
        // since we're handling this, log to elmah

    var ex = filterContext.Exception ?? new Exception("No further information exists.");
    LogException(ex);

    filterContext.ExceptionHandled = true;
    var data = new ErrorPresentation
        {
            ErrorMessage = HttpUtility.HtmlEncode(ex.Message),
            TheException = ex,
            ShowMessage = !(filterContext.Exception == null),
            ShowLink = false
        };
    filterContext.Result = View("ErrorPage", data);
}

我认为您不能基于带有HandleError属性的HttpCode显示特定的ErrorPage,我更愿意为此使用HttpModule。假设我有文件夹“ErrorPages”,其中每个特定错误都有不同的页面,并且映射在web.config中指定,与常规web表单应用程序相同。下面是用于显示错误页面的代码:

public class ErrorHandler : BaseHttpModule{

public override void OnError(HttpContextBase context)
{
    Exception e = context.Server.GetLastError().GetBaseException();
    HttpException httpException = e as HttpException;
    int statusCode = (int) HttpStatusCode.InternalServerError;

    // Skip Page Not Found and Service not unavailable from logging
    if (httpException != null)
    {
        statusCode = httpException.GetHttpCode();

        if ((statusCode != (int) HttpStatusCode.NotFound) && (statusCode != (int) HttpStatusCode.ServiceUnavailable))
        {
            Log.Exception(e);
        }
    }

    string redirectUrl = null;

    if (context.IsCustomErrorEnabled)
    {
        CustomErrorsSection section = IoC.Resolve<IConfigurationManager>().GetSection<CustomErrorsSection>("system.web/customErrors");

        if (section != null)
        {
            redirectUrl = section.DefaultRedirect;

            if (httpException != null)
            {
                if (section.Errors.Count > 0)
                {
                    CustomError item = section.Errors[statusCode.ToString(Constants.CurrentCulture)];

                    if (item != null)
                    {
                        redirectUrl = item.Redirect;
                    }
                }
            }
        }
    }

    context.Response.Clear();
    context.Response.StatusCode = statusCode;
    context.Response.TrySkipIisCustomErrors = true;

    context.ClearError();

    if (!string.IsNullOrEmpty(redirectUrl))
    {
        context.Server.Transfer(redirectUrl);
    }
}
公共类错误处理程序:BaseHttpModule{
公共覆盖无效OnError(HttpContextBase上下文)
{
异常e=context.Server.GetLastError().GetBaseException();
HttpException HttpException=e作为HttpException;
int statusCode=(int)HttpStatusCode.InternalServerError;
//跳过未找到的页面和记录的服务不可用
if(httpException!=null)
{
statusCode=httpException.GetHttpCode();
if((statusCode!=(int)HttpStatusCode.NotFound)和&(statusCode!=(int)HttpStatusCode.ServiceUnavailable))
{
日志异常(e);
}
}
字符串重定向URL=null;
if(context.IsCustomErrorEnabled)
{
CustomErrorsSection=IoC.Resolve().GetSection(“system.web/customErrors”);
if(节!=null)
{
redirectUrl=section.DefaultRedirect;
if(httpException!=null)
{
如果(section.Errors.Count>0)
{
CustomError item=section.Errors[statusCode.ToString(Constants.CurrentCulture)];
如果(项!=null)
{
重定向URL=item.Redirect;
}
}
}
}
}
context.Response.Clear();
context.Response.StatusCode=状态码;
context.Response.tryskipiiscustomerors=true;
context.ClearError();
如果(!string.IsNullOrEmpty(重定向URL))
{
context.Server.Transfer(重定向URL);
}
}

}多亏了kazimanzurrashaid,我在Global.asax.cs上完成了以下工作:

protected void Application_Error()
{
    Exception unhandledException = Server.GetLastError();
    HttpException httpException = unhandledException as HttpException;
    if (httpException == null)
    {
        Exception innerException = unhandledException.InnerException;
        httpException = innerException as HttpException;
    }

    if (httpException != null)
    {
        int httpCode = httpException.GetHttpCode();
        switch (httpCode)
        {
            case (int) HttpStatusCode.Unauthorized:
                Response.Redirect("/Http/Error401");
                break;
        }
    }
}
根据我需要支持的任何其他HTTP错误代码,我将能够向HttpContoller添加更多页面。

阅读本文的其他人可能遇到的另一种可能性(在您的情况下不是这样)是您的错误页面本身抛出错误,或者未实现:

 System.Web.Mvc.ViewPage<System.Web.Mvc.HandleErrorInfo>
System.Web.Mvc.ViewPage
如果是这种情况,那么您将得到默认的错误页面(否则您将得到一个无限循环,因为它将不断尝试将自己发送到您的自定义错误页面)。这对我来说不是很明显


此模型是发送到错误页面的模型。如果您的错误页面使用与站点其他部分相同的母版页,并且需要任何其他模型信息,则您需要创建自己的
[HandleError]
属性类型或覆盖
OneException
或其他内容。

我选择了Controller.OneException()方法,对我来说,这是一个合乎逻辑的选择——因为我选择了ASP.NETMVC,所以我更喜欢停留在框架级别,如果可能的话,避免弄乱底层机制

我遇到了以下问题:

如果视图中发生异常,则该视图的部分输出将与错误消息一起出现在屏幕上

在设置filterContext.Result之前,我通过清除响应修复了此问题-如下所示:

        filterContext.HttpContext.Response.Clear(); // gets rid of any garbage
        filterContext.Result = View("ErrorPage", data);
希望这能为其他人节省一些时间:-)

杰夫·阿特伍德的作品对MVC非常有用。您可以完全在web.config中配置它,而无需对MVC项目源代码进行任何更改。但是,它需要一个小的修改来返回原始HTTP状态,而不是
200
状态。见此相关报道

基本上,在Handler.vb中,您可以添加如下内容:

标题中的“
”。。。
Private _exhttppexas HttpException=无
'在公共子句柄异常的顶部(ByVal ex作为异常)。。。
HttpContext.Current.Response.StatusCode=500
如果TypeOf ex是HttpException,那么
_exHttpEx=CType(ex,HttpException)
HttpContext.Current.Response.StatusCode=\u exhttppex.GetHttpCode()
如果结束

您已经指出,如果没有解决无法为HTTP错误代码提供错误处理的真正问题,我的一个陈述是不正确的。我可以解释发生了什么,但我需要更多信息,以便告诉您如何正确处理应用程序。HandleError在操作中工作,并且通常不会在操作中抛出HttpExceptions。而不是猜测你到底是什么
        filterContext.HttpContext.Response.Clear(); // gets rid of any garbage
        filterContext.Result = View("ErrorPage", data);
     protected override void OnException (ExceptionContext filterContext )
    {
        if (filterContext != null && filterContext.Exception != null)
        {
            filterContext.ExceptionHandled = true;
            this.View("Error").ViewData["Exception"] = filterContext.Exception.Message;
            this.View("Error").ExecuteResult(this.ControllerContext);
        }
    }