【问题标题】:Is it possible to redirect to view from a non-controller class in MVC是否可以从 MVC 中的非控制器类重定向到视图
【发布时间】:2016-08-15 00:00:10
【问题描述】:

正在使用 NLOG 进行日志记录,并且在发生日志记录的地方有一个单独的类@全局级别。根据要求,必须在日志记录结束后从该类重定向到“错误”视图 (Error.cshtml)。

但它是一个非控制器类,因此不能使用RedirectToAction() 或简单的return View("Error") 等常用方法。

有没有办法做到这一点?我试过Response.Redirect(),但什么也没做。

HttpContext.Current.Response.Redirect("/Help/Error",true);

Error.cshtml 是一个纯 HTML 文件,其文本类似于 有一些错误...请联系管理员,该文件位于 Views/Shared/* 文件夹下。

日志记录类存在于一个单独的文件夹中,比如根文件夹下的logging

在每次调用 Action 方法时,如果发生任何异常,则自动调用记录器,这就是记录的内容,最后应该重定向到错误视图。

【问题讨论】:

  • 需要提供更多关于如何捕获错误的信息。让您访问此日志记录代码的代码路径是什么。
  • @AaronLS,也包括了这些信息。请参阅帖子中的编辑。
  • 您是否有理由希望在外部类中使用该代码?您不能将代码从该类移动到您的(基本)控制器中的OnException 事件吗?
  • @Shyju,是的,可能存在并且它已经存在......而且无法将其移动到基本控制器。但从你的评论听起来好像没有办法完成这件事。这听起来也有点合乎逻辑。让我们知道。
  • @Shyju 指的是全局错误处理代码,它可以捕获任何错误,然后通过日志库记录它们,然后重定向到错误页面。谷歌快速搜索的结果:dusted.codes/….

标签: c# asp.net-mvc


【解决方案1】:

您可以创建自己的基本控制器并在 oneexception 事件中处理异常

public class BaseController : Controller
{
    protected override void OnException(ExceptionContext filterContext)
    {
       //Do your logging
       // and redirect / return error view
        filterContext.ExceptionHandled = true;
        // If the exception occured in an ajax call. Send a json response back
        // (you need to parse this and display to user as needed at client side)
        if (filterContext.HttpContext.Request.Headers["X-Requested-With"]=="XMLHttpRequest")
        {
            filterContext.Result = new JsonResult
            {
                JsonRequestBehavior = JsonRequestBehavior.AllowGet,
                Data = new { Error = true, Message = filterContext.Exception.Message }
            };
            filterContext.HttpContext.Response.StatusCode = 500; // Set as needed
        }
        else
        {
            filterContext.Result = new ViewResult { ViewName = "Error.cshtml" }; 
            //Assuming the view exists in the "~/Views/Shared" folder
        }
    }
}

现在对于您的其他控制器,从这个 bascontroller 继承。

public class ProductsController : BaseController 
{
   public ActionResult Die()
   {
     throw new Exception("I lost!");
   }
}

如果您想重定向(新的 GET 调用)到您的错误操作方法,您可以将 ViewResult 替换为 RedirectToRouteResult

filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary {
                                               {"controller", "Home"}, {"action", "Error"}
                                              };

【讨论】:

  • 对不起,但无法更改代码,因为它是现有代码,但绝对可以帮助其他人......很好的建议。
  • @Rahul 您所说的只是“自动调用记录器”,因此我们将在没有该信息的情况下推荐解决方案。
  • @AaronLS,我会尽快在帖子中添加相关信息。它是很久以前由别人写的,我不太了解 MVC
  • 很抱歉长时间延迟感谢您的好答案。
【解决方案2】:

您没有说“自动调用记录器”如何自动调用日志记录代码。所以我要推荐一个 HandleErrorAttribute。这要求您在共享视图文件夹中有一个 Error.cshtml,但您可以在 filterContext.Result 中指定不同的视图

public class CustomErrorAttribute : HandleErrorAttribute 
{

    public override void OnException(ExceptionContext filterContext)
    {
        filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;// This causes the webconfig httpErrors section to be ignored, since we are handling the exception
        filterContext.ExceptionHandled = true;

        //... log error

        filterContext.HttpContext.Response.ClearContent();// Removes partially rendered content

        // just information to be passed in the view model, this does NOT define which view is displayed next.  It tells us where the error came from.
        var controllerName = (string)filterContext.RouteData.Values["controller"];
        var actionName = (string)filterContext.RouteData.Values["action"];
        var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
        // This presents an error page view.  By default if a View is not passed to the Attribute, then this is Error.cshtml in Shared.
        filterContext.Result = new ViewResult
        {
            ViewName = View,  // View & Master are parameters from the attribute e.g. [ErrorAttribute(View="OtherErrorView")], by default the view is the "Error.cshtml" view
            MasterName = Master,
            ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
            TempData = filterContext.Controller.TempData
        };

        filterContext.Exception = null;


    }
}

【讨论】:

  • 很抱歉长时间延迟感谢您的好答案。
猜你喜欢
  • 2018-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-25
  • 1970-01-01
相关资源
最近更新 更多