首页 文章

ASP.NET MVC HandleError

提问于
浏览
106

如何在asp.net MVC Preview 5中使用 [HandleError] 过滤器?
我在我的Web.config文件中设置了customErrors

<customErrors mode="On" defaultRedirect="Error.aspx">
  <error statusCode="403" redirect="NoAccess.htm"/>
  <error statusCode="404" redirect="FileNotFound.htm"/>
</customErrors>

并将[HandleError]放在我的Controller类上面,如下所示:

[HandleError]
public class DSWebsiteController: Controller
{
    [snip]
    public ActionResult CrashTest()
    {
        throw new Exception("Oh Noes!");
    }
}

然后我让我的控制器从这个类继承并在它们上调用CrashTest() . 视觉工作室在错误时停止并按下f5继续后,我被重新路由到Error.aspx?aspxerrorpath = / sxi.mvc / CrashTest(其中sxi是所用控制器的名称 . 当然道路无法找到,我得到“'''应用程序中的服务器错误 . ”404 .

这个站点从预览3移植到5.除了错误处理之外,所有东西都运行(没有太多工作要移植) . 当我创建一个完整的新项目时,错误处理似乎有效 .

想法?

--Note--
由于这个问题现在有超过3K的视图,我认为放入我目前使用的(ASP.NET MVC 1.0)是有益的 . 在mvc contrib project中有一个名为"RescueAttribute"的辉煌属性你也应该检查一下;)

6 回答

  • 14
    [HandleError]
    

    当你只为你的类提供HandleError属性时(或者你的动作方法),当发生未处理的异常时,MVC将首先在Controller的View文件夹中查找名为“Error”的相应视图 . 如果它找不到它,那么它将继续查看共享视图文件夹(默认情况下应该包含Error.aspx文件)

    [HandleError(ExceptionType = typeof(SqlException), View = "DatabaseError")]
    [HandleError(ExceptionType = typeof(NullReferenceException), View = "LameErrorHandling")]
    

    您还可以使用有关所查找的异常类型的特定信息来堆叠其他属性 . 此时,您可以将错误定向到默认“错误”视图以外的特定视图 .

    有关更多信息,请查看Scott Guthrie's blog post .

  • 23

    还应注意,未将http错误代码设置为500的错误

    (例如UnauthorizedAccessException)

    HandleError过滤器不会处理 .

  • -1

    MVC中的属性在 get and post 方法的错误处理中非常有用,它也跟踪 ajax call .

    在应用程序中创建一个基本控制器,并在主控制器(EmployeeController)中继承它 .

    public class EmployeeController : BaseController

    在基本控制器中添加以下代码 .

    /// <summary>
    /// Base Controller
    /// </summary>
    public class BaseController : Controller
    {       
        protected override void OnException(ExceptionContext filterContext)
        {
            Exception ex = filterContext.Exception;
    
            //Save error log in file
            if (ConfigurationManager.AppSettings["SaveErrorLog"].ToString().Trim().ToUpper() == "TRUE")
            {
                SaveErrorLog(ex, filterContext);
            }
    
            // if the request is AJAX return JSON else view.
            if (IsAjax(filterContext))
            {
                //Because its a exception raised after ajax invocation
                //Lets return Json
                filterContext.Result = new JsonResult()
                {
                    Data = Convert.ToString(filterContext.Exception),
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet
                };
            }
            else
            {
                filterContext.ExceptionHandled = true;
                filterContext.HttpContext.Response.Clear();
    
                filterContext.Result = new ViewResult()
                {
                    //Error page to load
                    ViewName = "Error",
                    ViewData = new ViewDataDictionary()
                };
    
                base.OnException(filterContext);
            }
        }
    
        /// <summary>
        /// Determines whether the specified filter context is ajax.
        /// </summary>
        /// <param name="filterContext">The filter context.</param>
        private bool IsAjax(ExceptionContext filterContext)
        {
            return filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest";
        }
    
        /// <summary>
        /// Saves the error log.
        /// </summary>
        /// <param name="ex">The ex.</param>
        /// <param name="filterContext">The filter context.</param>
        void SaveErrorLog(Exception ex, ExceptionContext filterContext)
        {
            string logMessage = ex.ToString();
    
            string logDirectory = Server.MapPath(Url.Content("~/ErrorLog/"));
    
            DateTime currentDateTime = DateTime.Now;
            string currentDateTimeString = currentDateTime.ToString();
            CheckCreateLogDirectory(logDirectory);
            string logLine = BuildLogLine(currentDateTime, logMessage, filterContext);
            logDirectory = (logDirectory + "\\Log_" + LogFileName(DateTime.Now) + ".txt");
    
            StreamWriter streamWriter = null;
            try
            {
                streamWriter = new StreamWriter(logDirectory, true);
                streamWriter.WriteLine(logLine);
            }
            catch
            {
            }
            finally
            {
                if (streamWriter != null)
                {
                    streamWriter.Close();
                }
            }
        }
    
        /// <summary>
        /// Checks the create log directory.
        /// </summary>
        /// <param name="logPath">The log path.</param>
        bool CheckCreateLogDirectory(string logPath)
        {
            bool loggingDirectoryExists = false;
            DirectoryInfo directoryInfo = new DirectoryInfo(logPath);
            if (directoryInfo.Exists)
            {
                loggingDirectoryExists = true;
            }
            else
            {
                try
                {
                    Directory.CreateDirectory(logPath);
                    loggingDirectoryExists = true;
                }
                catch
                {
                }
            }
    
            return loggingDirectoryExists;
        }
    
        /// <summary>
        /// Builds the log line.
        /// </summary>
        /// <param name="currentDateTime">The current date time.</param>
        /// <param name="logMessage">The log message.</param>
        /// <param name="filterContext">The filter context.</param>       
        string BuildLogLine(DateTime currentDateTime, string logMessage, ExceptionContext filterContext)
        {
            string controllerName = filterContext.RouteData.Values["Controller"].ToString();
            string actionName = filterContext.RouteData.Values["Action"].ToString();
    
            RouteValueDictionary paramList = ((System.Web.Routing.Route)(filterContext.RouteData.Route)).Defaults;
            if (paramList != null)
            {
                paramList.Remove("Controller");
                paramList.Remove("Action");
            }
    
            StringBuilder loglineStringBuilder = new StringBuilder();
    
            loglineStringBuilder.Append("Log Time : ");
            loglineStringBuilder.Append(LogFileEntryDateTime(currentDateTime));
            loglineStringBuilder.Append(System.Environment.NewLine);
    
            loglineStringBuilder.Append("Username : ");
            loglineStringBuilder.Append(Session["LogedInUserName"]);
            loglineStringBuilder.Append(System.Environment.NewLine);
    
            loglineStringBuilder.Append("ControllerName : ");
            loglineStringBuilder.Append(controllerName);
            loglineStringBuilder.Append(System.Environment.NewLine);
    
            loglineStringBuilder.Append("ActionName : ");
            loglineStringBuilder.Append(actionName);
            loglineStringBuilder.Append(System.Environment.NewLine);
    
            loglineStringBuilder.Append("----------------------------------------------------------------------------------------------------------");
            loglineStringBuilder.Append(System.Environment.NewLine);
    
            loglineStringBuilder.Append(logMessage);
            loglineStringBuilder.Append(System.Environment.NewLine);
            loglineStringBuilder.Append("==========================================================================================================");
    
            return loglineStringBuilder.ToString();
        }
    
        /// <summary>
        /// Logs the file entry date time.
        /// </summary>
        /// <param name="currentDateTime">The current date time.</param>
        string LogFileEntryDateTime(DateTime currentDateTime)
        {
            return currentDateTime.ToString("dd-MMM-yyyy HH:mm:ss");
        }
    
        /// <summary>
        /// Logs the name of the file.
        /// </summary>
        /// <param name="currentDateTime">The current date time.</param>
        string LogFileName(DateTime currentDateTime)
        {
            return currentDateTime.ToString("dd_MMM_yyyy");
        }
    
    }
    

    ================================================

    Finds the Directory : Root/App_Start/FilterConfig.cs

    添加以下代码:

    /// <summary>
    /// Filter Config
    /// </summary>
    public class FilterConfig
    {
        /// <summary>
        /// Registers the global filters.
        /// </summary>
        /// <param name="filters">The filters.</param>
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }
    }
    

    Track AJAX Error:

    在布局页面加载中调用CheckAJAXError函数 .

    function CheckAJAXError() {
        $(document).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) {
    
            var ex;
            if (String(thrownError).toUpperCase() == "LOGIN") {
                var url = '@Url.Action("Login", "Login")';
                window.location = url;
            }
            else if (String(jqXHR.responseText).toUpperCase().indexOf("THE DELETE STATEMENT CONFLICTED WITH THE REFERENCE CONSTRAINT") >= 0) {
    
                toastr.error('ReferanceExistMessage');
            }
            else if (String(thrownError).toUpperCase() == "INTERNAL SERVER ERROR") {
                ex = ajaxSettings.url;
                //var url = '@Url.Action("ErrorLog", "Home")?exurl=' + ex;
                var url = '@Url.Action("ErrorLog", "Home")';
                window.location = url;
            }
        });
    };
    
  • 155

    将http错误代码解为500这是一个名为[ERROR]的属性,将其置于一个动作上

    public class Error: System.Web.Mvc.HandleErrorAttribute
    {
        public override void OnException(System.Web.Mvc.ExceptionContext filterContext)
        {
    
                if (filterContext.HttpContext.IsCustomErrorEnabled)
                {
                    filterContext.ExceptionHandled = true;
    
                }
                base.OnException(filterContext);
                //OVERRIDE THE 500 ERROR  
               filterContext.HttpContext.Response.StatusCode = 200;
        }
    
        private static void RaiseErrorSignal(Exception e)
        {
            var context = HttpContext.Current;
          // using.Elmah.ErrorSignal.FromContext(context).Raise(e, context);
        } 
    
    }
    

    //例:

    [Error]
    [HandleError]
    [PopulateSiteMap(SiteMapName="Mifel1", ViewDataKey="Mifel1")]
    public class ApplicationController : Controller
    {
    }
    
  • 4

    您缺少Error.aspx :)在预览5中,它位于您的Views / Shared文件夹中 . 只需从新的预览5项目中复制它 .

  • 16
    [HandleError]
        public class ErrorController : Controller
        {        
            [AcceptVerbs(HttpVerbs.Get)]
            public ViewResult NotAuthorized()
            {
                //401
                Response.StatusCode = (int)HttpStatusCode.Unauthorized;
    
            return View();
        }
    
        [AcceptVerbs(HttpVerbs.Get)]
        public ViewResult Forbidden()
        {
            //403
            Response.StatusCode = (int)HttpStatusCode.Forbidden;
    
            return View();
        }
    
        [AcceptVerbs(HttpVerbs.Get)]
        public ViewResult NotFound()
        {
            //404
            Response.StatusCode = (int)HttpStatusCode.NotFound;
            return View();
        }
    
        public ViewResult ServerError()
        {
            //500
            Response.StatusCode = (int)HttpStatusCode.NotFound;
            return View();
        }
    

    }

相关问题