【问题标题】:How to render a View once you're in the Application_Error event handler without redirecting the user?如何在 Application_Error 事件处理程序中呈现视图而不重定向用户?
【发布时间】:2019-09-30 13:48:22
【问题描述】:

假设您的应用程序抛出了一个不在ControllerActionInvoker.InvokeAction 方法范围内的异常。

这可能发生,例如,如果用户输入了错误的 URL,该 URL 不能解析为任何现有控制器或操作的名称。

http://www.example.com/doesNotExist

该 URL 会抛出一个HttpException,状态码为 404。

然后您可以在 Application 对象的 Error 事件处理程序中处理它。

// Global.asax.cs
public void Application_Error()
{
  HttpException exception = Server.GetLastError() as HttpException;

  // do whatever with it
}

从这里开始,是否可以在不实际将用户重定向到将呈现视图的新 URL 的情况下呈现 ASP.NET MVC 视图

// Global.asax.cs
public void Application_Error()
{
  HttpException exception = Server.GetLastError() as HttpException;

  // can I *render* a View here?
  // In other words, can I execute a ViewResult here?
  // Can I get back into MVC from here?
  // But without redirecting the user. Just re-writing the Response object?
}

我在这里看到的所有示例都只是在 Response 对象上设置了 HTTP StatusCodeStatusDescription。我想从这里返回View而不将用户重定向到查看网址

我正在使用面向 .NET Framework 4.6.1 的 ASP.NET MVC 5.2.6。

【问题讨论】:

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


    【解决方案1】:

    您想要实现什么但没有将用户重定向到错误页面?

    我们自己的Application_Error() 实现在我们的错误控制器上执行方法之前捕获并记录错误到我们的数据库,但这实际上只是将用户重定向到一个友好的页面,我们向他们显示有关错误的相关信息,以便他们可以例如,报告它;

    Global.aspx.cs

        protected void Application_Error()
        {
            string showerrors = ConfigurationManager.AppSettings["ShowErrors"];
            string appid = ConfigurationManager.AppSettings["ApplicationId"];
    
            if (showerrors != "Y")
            {
                Exception ex = Server.GetLastError();
                var httpex = ex as HttpException;
    
                if (HttpContext.Current != null)
                {
                    Response.Clear();
                }
                Server.ClearError();
    
                if (ex is HttpException && ex.InnerException is ViewStateException)
                {
                    Response.Redirect(Request.Url.AbsoluteUri);
                    return;
                }
    
                ApplicationError err = new ApplicationError();
    
                err.ApplicationId = appid;
                err.ErrorCode = httpex == null ? 0 : httpex.GetHttpCode();
                err.ErrorMessage = ex.Message;
    
                err.UserId = User != null ? User.Identity.Name : null;
                err.IPAddress = Request.ServerVariables["REMOTE_HOST"];
                err.Referrer = Request.ServerVariables["HTTP_REFERER"];
                err.Url = Request.Url.ToString();
                err.StackTrace = ex.StackTrace;
    
                string[] errorstoignore = new string[] { "__VIEWSTATE", "PASSWORD" };
    
                StringBuilder sbfv = new StringBuilder();
                foreach (string s in Request.Form.AllKeys)
                {
                    if (!errorstoignore.Contains(s.ToUpper()))
                    {
                        if (sbfv.Length > 0)
                        {
                            sbfv.Append(", ");
                        }
                        if (!s.ToLower().Contains("password"))
                        {
                            sbfv.Append(s + ":" + Request.Form[s] + "\n");
                        }
                        else
                        {
                            sbfv.Append(s + ":********" + "\n");
                        }
                    }
                }
                err.FormValues = sbfv.ToString();
                err.ErrorDate = DateTime.Now;
    
                ApplicationServices asvcs = new ApplicationServices();
                asvcs.AddError(err);
    
                var routeData = new RouteData();
                routeData.Values["controller"] = "Error";
                routeData.Values["action"] = "Index";
                routeData.Values["id"] = err.ErrorId;
                routeData.Values["exception"] = ex;
    
                IController errorsController = new ErrorController();
                var rc = new RequestContext(new HttpContextWrapper(Context), routeData);
                errorsController.Execute(rc);
            }
        }
    

    ErrorController.cs

        [AllowAnonymous]
        [OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
        [NoAntiForgeryCheck]
        public ActionResult Index(int id, Exception exception)
        {
            string errortitle = "Application Error";
            int errid = (exception is HttpException) ? ((HttpException)exception).GetHttpCode() : 0;
            string msg = exception.Message;
    
            switch (errid)
            {
                case 0:
                    errortitle = "Internal Application Error";
                    msg = "See error log or debug";
                    break;
                case 400:
                    //Bad Request
                    errortitle = "Security Violation";
                    msg = "The page could not be opened.";
                    break;
                case 401:
                    //Unauthorized
                    errortitle = "Security Violation";
                    msg = "The page could not be opened.";
                    break;
                case 402:
                    //Payment Required
                    errortitle = "Payment Required";
                    break;
                case 403:
                    //Forbidden
                    errortitle = "Security Violation";
                    msg = "The page could not be opened.";
                    break;
                case 404:
                    //Not Found
                    errortitle = "Navigation Error";
                    msg = "The page could not be opened.";
                    break;
                case 405:
                    //Method Not Allowed
                    errortitle = "Security Violation";
                    msg = "The page could not be opened.";
                    break;
                case 406:
                    //Not Acceptable
                    errortitle = "Not Acceptable";
                    break;
                case 500:
                    //Internal Server Error
                    errortitle = "Internal Server Error";
                    if (exception is HttpAntiForgeryException)
                    {
                        errortitle = "Security Violation";
                    }
                    break;
                case 501:
                    //Not Implemented
                    errortitle = "Not Implemented";
                    break;
                case 502:
                    //Bad Gateway
                    errortitle = "Bad Gateway";
                    break;
            }
            //Generate an error reference
            string appid = ConfigurationManager.AppSettings["ApplicationId"];
            string errorref = appid + id.ToString("00000");
            ViewBag.Id = id;
            ViewBag.ErrorTitle = errortitle;
            ViewBag.ErrorMessage = msg;
            ViewBag.IsFullPage = "N";
            ViewBag.ErrorAction = "Please contact your Technical Support Desk quoting reference " + errorref + " to report this error.";
            //ViewBag.ReturnUrl = Request.UrlReferrer == null ? String.Empty : Request.UrlReferrer.AbsoluteUri.ToString();
    
            return PartialView();
        }
    

    这是否对你有帮助我不确定,直到我了解你想要做什么。

    【讨论】:

    • 我想直接从 Application_Error 事件处理程序呈现视图,而不必调用操作,也不必通过 302/301 将用户重定向到 URL/路由/操作。您的代码正在调用一个动作,所以这不是我要找的。我不想采取行动的原因是我不希望我的错误页面有 URL。我已经想到了一个解决方案并实施了它。我会在几天后发布一个关于它的答案。
    猜你喜欢
    • 1970-01-01
    • 2018-06-09
    • 2013-01-15
    • 1970-01-01
    • 2013-07-21
    • 2017-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多