如何为对象提供HandleErrorInfo模型?

时间:2014-07-24 11:54:30

标签: asp.net-mvc error-handling

我正在编写ASP.NET MVC应用程序,但遇到了以下问题。我想制作自定义错误页面,其中包含有关错误的详细信息(例如错误消息或导致错误的控制器),但我无法使用HandleErrorInfo对象在视图上提供模型。

首先,我配置了Web.config文件来处理自定义错误:

<customErrors mode="On" defaultRedirect="~/Error">
  <error statusCode="404" redirect="~/Error/NotFound"/>
</customErrors>

然后我创建了错误控制器来管理错误视图:

public class ErrorController : Controller
{
    public ActionResult Index()
    {
        return View("Error");
    }

    public ViewResult NotFound()
    {
        Response.StatusCode = 404;
        return View("NotFound");
    }
}

在视图上我添加了模型类型:

@model System.Web.Mvc.HandleErrorInfo

但是模型每次都是null,我不知道如何将带有错误详细信息的正确对象传递给视图以及应该在哪里创建该对象。你能帮助我吗?甚至可以这样做吗?

3 个答案:

答案 0 :(得分:15)

所以你在这里处理两个不同的'层'。 <customErrors>是主要ASP.NET框架的一部分。然后HandleError是MVC框架的一部分。当您使用<customErrors>时,ASP.NET不知道如何将异常信息传递到视图中,它只会将您加载/重定向到错误页面。

要使视图正常工作,您需要将所有内容保留在MVC生态系统中。因此,您需要使用HandleErrorAttribute或变量。 You can see in the source code of the attribute它会尝试检测何时发生未处理的异常,并且如果启用了自定义错误,则会转动一个新的ViewResult,其中包含HandleErrorInfo的实例,其中包含异常信息

需要注意的是,在默认的MVC项目中,HandleErrorAttribute被应用为App_Start/FilterConfig.cs文件中的全局过滤器。

答案 1 :(得分:8)

我发现了另一种方式。发送错误模型以从控制器查看。

<强> 1。 Global.asax

protected void Application_Error(object sender, EventArgs e)
{
    var httpContext = ((MvcApplication)sender).Context;
    var currentController = " ";
    var currentAction = " ";
    var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));

    if (currentRouteData != null)
    {
        if (currentRouteData.Values["controller"] != null && !String.IsNullOrEmpty(currentRouteData.Values["controller"].ToString()))
        {
            currentController = currentRouteData.Values["controller"].ToString();
        }

        if (currentRouteData.Values["action"] != null && !String.IsNullOrEmpty(currentRouteData.Values["action"].ToString()))
        {
            currentAction = currentRouteData.Values["action"].ToString();
        }
    }

    var ex = Server.GetLastError();
    //var controller = new ErrorController();
    var routeData = new RouteData();
    var action = "GenericError";

    if (ex is HttpException)
    {
        var httpEx = ex as HttpException;

        switch (httpEx.GetHttpCode())
        {
            case 404:
                action = "NotFound";
                break;

            // others if any
        }
    }

    httpContext.ClearError();
    httpContext.Response.Clear();
    httpContext.Response.StatusCode = ex is HttpException ? ((HttpException)ex).GetHttpCode() : 500;
    httpContext.Response.TrySkipIisCustomErrors = true;

    routeData.Values["controller"] = "Error";
    routeData.Values["action"] = action;
    routeData.Values["exception"] = new HandleErrorInfo(ex, currentController, currentAction);

    IController errormanagerController = new ErrorController();
    HttpContextWrapper wrapper = new HttpContextWrapper(httpContext);
    var rc = new RequestContext(wrapper, routeData);
    errormanagerController.Execute(rc);
}

<强> 2。错误控制器:

public class ErrorController : Controller
{
    //
    // GET: /Error/

    public ActionResult Index()
    {
        return RedirectToAction("GenericError", new HandleErrorInfo(new HttpException(403, "Dont allow access the error pages"), "ErrorController", "Index"));
    }

    public ViewResult GenericError(HandleErrorInfo exception)
    {            
        return View("Error", exception);
    }

    public ViewResult NotFound(HandleErrorInfo exception)
    {         
        ViewBag.Title = "Page Not Found";
        return View("Error", exception);
    }        
}

第3。查看/共享/ Error.cshtml:

@model System.Web.Mvc.HandleErrorInfo
@{   
    ViewBag.Title = ViewBag.Title ?? "Internal Server Error";
}
<div class="list-header clearfix">
    <span>Error : @ViewBag.Title</span>
</div>
<div class="list-sfs-holder">
    <div class="alert alert-error">
        An unexpected error has occurred. Please contact the system administrator.
    </div>
    @if (Model != null && HttpContext.Current.IsDebuggingEnabled)
    {
        <div>
            <p>
                <b>Exception:</b> @Model.Exception.Message<br />
                <b>Controller:</b> @Model.ControllerName<br />
                <b>Action:</b> @Model.ActionName
            </p>
            <div style="overflow: scroll">
                <pre>
                    @Model.Exception.StackTrace
                </pre>
            </div>
        </div>
    }
</div>

<强> 4。 web.config:

<system.web>
    <customErrors mode="Off" />
</system.web>

致谢: https://thatsimpleidea.wordpress.com/2013/10/28/mvc-error-page-implementation/#comment-166

答案 2 :(得分:1)

这对我没有用,但启发我发现我的Global.asax.Application_Start()没有像FilterConfig那样注册FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 类:

class Car(models.Model):
    name = models.CharField(max_length=60)

这与Steven V的答案相结合解决了我的null模型问题。