【问题标题】:ASP.NET MVC Error Handling in Areas区域中的 ASP.NET MVC 错误处理
【发布时间】:2015-02-20 07:49:49
【问题描述】:

我正在开发 ASP.NET MVC 应用程序,为了处理错误,我遵循了这个tutorial。所以,FilterConfig.cs中的代码:

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

我在 Controllers 文件夹中添加了一个 ErrorController:

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

我还创建了 View 以在 Views/Error 中显示错误:

@model System.Web.Mvc.HandleErrorInfo

@{
    ViewBag.Title = "Index";
}

<h1 class="text-danger">Custom Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>

<h2>Exception details</h2>
<p>
    Controller: @Model.ControllerName <br />
    Action: @Model.ActionName<br />
    Message: @Model.Exception.Message <br />
    StackTrace: <br />
</p>
<pre>Exception: @Model.Exception.StackTrace</pre>

然后我创建了 Admin Area 并将所有管理员的视图移动到 Admin 文件夹。管理区有自己的布局,与主布局不同。

为了处理管理区域中的错误,我还在~/Areas/Admin/Controllers 中创建了ErrorController.cs 并在~/Areas/Admin/Views/Error 中创建了它的视图,以在管理员的布局中显示错误,但是当错误发生在管理员页面时。它将在主布局中显示消息(~/Views/Error)

如何处理MVC中各个区域的错误?

CustomErrorHandlerAttribute.cs

public class CustomHandleErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        //base.OnException(filterContext);

        // Log the error using Elmah & NLog
        if (filterContext.Exception is DbEntityValidationException)
        {
            DbEntityValidationException dbevex = filterContext.Exception as DbEntityValidationException;

            var errorMessages = (from eve in dbevex.EntityValidationErrors
                                 let entity = eve.Entry.Entity.GetType().Name
                                 from ev in eve.ValidationErrors
                                 select new
                                 {
                                     Entity = entity,
                                     PropertyName = ev.PropertyName,
                                     ErrorMessage = ev.ErrorMessage
                                 });

            var fullErrorMessage = string.Join("; ", errorMessages.Select(e => string.Format("[Entity: {0}, Property: {1}] {2}", e.Entity, e.PropertyName, e.ErrorMessage)));
            var exceptionMessage = string.Concat(dbevex.Message, " The validation errors are: ", fullErrorMessage);
            LogUtility.logger.Error(exceptionMessage);
            ErrorSignal.FromCurrentContext().Raise(new DbEntityValidationException(exceptionMessage, dbevex.EntityValidationErrors));
        }
        else
        {
            LogUtility.logger.Error(filterContext.Exception.Message, filterContext.Exception);
        }

        if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
        {
            return;
        }
        if (new HttpException(null, filterContext.Exception).GetHttpCode() != 500)
        {
            return;
        }
        if (!ExceptionType.IsInstanceOfType(filterContext.Exception))
        {
            return;
        }

        // If the request is AJAX return JSON else view
        if (filterContext.HttpContext.Request.IsAjaxRequest()) //if (filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
        {
            // Because it's exception raised after ajax invocation, return Json
            filterContext.Result = new JsonResult
            {
                Data = new
                {
                    error = true,
                    message = filterContext.Exception.Message
                },
                JsonRequestBehavior = JsonRequestBehavior.AllowGet
            };
        }
        else
        {
            var controllerName = (string)filterContext.RouteData.Values["controller"];
            var actionName = (string)filterContext.RouteData.Values["action"];
            var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);

            filterContext.Result = new ViewResult()
            {
                ViewName = View,
                MasterName = Master,
                ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
                TempData = filterContext.Controller.TempData
            };
        }

        filterContext.ExceptionHandled = true;
        filterContext.HttpContext.Response.Clear();
        filterContext.HttpContext.Response.StatusCode = 500;
        filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
    }
}

RouteConfig.cs

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        // Visual Studio 2013 Browser Link caused
        // "The controller for path '/9ac086a69364466a841e03e001f946fd/arterySignalR/ping' could not be found."
#if DEBUG
        routes.IgnoreRoute("{*browserlink}", new { browserlink = @".*/arterySignalR/ping" });
#endif
        // with code above, we can still use Browser Link feature without getting error

        routes.MapRoute(
           "AxCustomer",
           "AxCustomer/{action}/{id}",
           new { controller = "AX_CUSTTABLE", action = "Index", id = UrlParameter.Optional },
           namespaces: new[] { "SalesSupportSystem.Controllers" }
        );

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            namespaces: new[] { "SalesSupportSystem.Controllers" }
        );
    }
}

【问题讨论】:

  • 你能把HandleErrorAttribute.csCustomHandleErrorAttribute.cs的代码贴出来吗?
  • @JoeMighty 我更新了问题,HandleErrorAttribute 是 MVC 的默认值
  • 这个问题在这里得到解答:stackoverflow.com/questions/15935069/…

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


【解决方案1】:

这是未经测试的,但您是否尝试在设置filterContext.Result 之前在filterContext.RouteData.Values["area"] = "Admin"; 中指定Admin 区域?

像这样:

filterContext.RouteData.Values["area"] = "Admin";
filterContext.Result = new ViewResult()
...

【讨论】:

  • 很奇怪。如果在ViewName = View 处添加调试点,View 有什么值?我的似乎按预期工作。
  • 您在RouteConfig.csAdminAreaRegistration.cs 中的路由是什么样的?
  • 对不起@JoeMighty,我昨天回家了。如果我在 ViewName 进行调试,RouteConfig.cs 的值为“错误”我更新了问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-16
  • 2018-02-27
  • 1970-01-01
  • 2011-08-25
  • 1970-01-01
  • 2011-06-10
  • 2014-03-26
相关资源
最近更新 更多