C# 是否可以从MVC中的非控制器类重定向到视图

C# 是否可以从MVC中的非控制器类重定向到视图,c#,asp.net-mvc,C#,Asp.net Mvc,我们正在使用NLOG进行日志记录,并且日志记录发生的地方有单独的类@global level。根据要求,必须在日志记录结束后从该类重定向到“Error”视图(Error.cshtml) 但它是一个非控制器类,因此不能使用常规方法,如RedirectToAction()或简单地返回视图(“错误”) 有没有办法做到这一点?我尝试了Response.Redirect(),但什么也没做 HttpContext.Current.Response.Redirect("/Help/Error",true);

我们正在使用NLOG进行日志记录,并且日志记录发生的地方有单独的类@global level。根据要求,必须在日志记录结束后从该类重定向到“Error”视图(
Error.cshtml

但它是一个非控制器类,因此不能使用常规方法,如
RedirectToAction()
或简单地
返回视图(“错误”)

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

HttpContext.Current.Response.Redirect("/Help/Error",true);
Error.cshtml
是一个普通的HTML文件,其中包含一些错误的文本。。。请联系
Views/Shared/*
文件夹下的管理员

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


在每次调用Action方法时,如果发生任何异常,则会自动调用记录器,这将完成日志记录,并最终重定向到错误视图。

您可以创建自己的基本控制器,并在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
        }
    }
}
现在,对于其他控制器,从该控制器继承

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"}
                                              };

您不会说日志代码是如何自动调用的“记录器被自动调用”。所以我要推荐一个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;


    }
}
公共类CustomErrorAttribute:HandleErrorAttribute
{
公共覆盖无效OneException(例外上下文筛选器上下文)
{
filterContext.HttpContext.Response.TrySkipIisCustomErrors=true;//这会导致忽略webconfig httpErrors部分,因为我们正在处理异常
filterContext.ExceptionHandled=true;
//…日志错误
filterContext.HttpContext.Response.ClearContent();//删除部分呈现的内容
//只是在视图模型中传递的信息,这并不定义下一个显示哪个视图。它告诉我们错误来自何处。
var controllerName=(字符串)filterContext.RouteData.Values[“controller”];
var actionName=(字符串)filterContext.RouteData.Values[“action”];
var model=newhandleerrorinfo(filterContext.Exception、controllerName、actionName);
//这将显示一个错误的页面视图。默认情况下,如果未将视图传递给属性,则这是Shared中的error.cshtml。
filterContext.Result=新的ViewResult
{
ViewName=View、//View&Master是属性中的参数,例如[ErrorAttribute(View=“OtherErrorView”)],默认情况下,视图是“Error.cshtml”视图
MasterName=Master,
ViewData=新的ViewDataDictionary(型号),
TempData=filterContext.Controller.TempData
};
filterContext.Exception=null;
}
}

需要提供有关如何捕获错误的更多信息。获取此日志代码的代码路径是什么。@AaronLS,也包括这些信息。请参阅文章中的编辑。您希望在外部类中使用该代码的原因是什么?您不能将代码从该类移动到(基本)控制器中的
OnException
事件吗?@Shyju,是的,可能存在,并且它是现有的一个。。。而且不能将其移动到基础控制器。但从你的评论看来,似乎没有办法做到这一点。这听起来也有点合乎逻辑。让我们知道。@Shyju所指的是拥有全局错误处理代码,该代码捕获任何错误,然后通过日志库记录这些错误,然后重定向到错误页面。谷歌快速搜索的结果:。抱歉,但无法更改代码,因为它是现有代码,但肯定可以帮助其他人。。。很好的建议。@Rahul您所说的只是“记录器自动被调用”,所以我们将在没有这些信息的情况下推荐解决方案。@AaronLS,我将很快在帖子中添加相关信息。这是很久以前其他人写的,我不太理解MVC。很抱歉,感谢这个好的答案耽搁了很长时间。很抱歉,感谢这个好的答案耽搁了很长时间。