如何处理 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] 放在我的控制器类上方,如下所示:
[HandleError]
public class DSWebsiteController: Controller
{
[snip]
public ActionResult CrashTest()
{
throw new Exception("Oh Noes!");
}
}
然后我让我的控制器从这个类继承并在它们上调用 CrashTest()。 Visual Studio 在错误处停止,按 f5 继续后,我被重新路由到 Error.aspx?aspxerrorpath=/sxi.mvc/CrashTest (其中 sxi 是使用的控制器的名称。当然找不到路径,我得到了“'/' 应用程序中的服务器错误。”404。
这个站点是从预览版 3 移植到 5 版的。除了错误处理之外,一切都在运行(移植的工作并不多)。当我创建一个完整的新项目时,错误处理似乎起作用了。
想法?
--注意--
由于这个问题现在有超过 3K 的浏览量,我认为将我目前使用的 (ASP.NET MVC 1.0) 放入其中会是有益的。在 mvc contrib project 中有一个名为“RescueAttribute”的出色属性您可能也应该检查一下;)
RescueAttribute
来源的链接:mvccontrib.codeplex.com/SourceControl/changeset/view/…
[HandleError]
当您仅向您的类(或您的操作方法)提供 HandleError 属性时,当发生未处理的异常时,MVC 将首先在控制器的视图文件夹中查找名为“错误”的相应视图。如果在那里找不到它,它将继续查看共享视图文件夹(默认情况下应该有一个 Error.aspx 文件)
[HandleError(ExceptionType = typeof(SqlException), View = "DatabaseError")]
[HandleError(ExceptionType = typeof(NullReferenceException), View = "LameErrorHandling")]
您还可以使用有关您正在查找的异常类型的特定信息来堆叠其他属性。此时,您可以将错误定向到默认“错误”视图以外的特定视图。
有关详细信息,请查看 Scott Guthrie's blog post。
还要注意的是没有设置http错误码为500的错误
(例如 UnauthorizedAccessException)
HandleError 过滤器不会处理。
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
{
}
MVC 中的属性在 get 和 post 方法的错误处理中非常有用,它还跟踪 ajax 调用。
在您的应用程序中创建一个基本控制器并在您的主控制器(EmployeeController)中继承它。
公共类 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");
}
}
=================================================
查找目录: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());
}
}
跟踪 AJAX 错误:
在布局页面加载中调用 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;
}
});
};
OnException
以处理异常”,但它的实现非常糟糕。
您缺少 Error.aspx :) 在预览版 5 中,它位于您的 Views/Shared 文件夹中。只需从新的 Preview 5 项目中复制它即可。
[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();
}
}
不定期副业成功案例分享
global.asax
内处理这个以向用户显示消息吗?