MVC 句柄错误

如何在 asp.net MVC 预览版5中使用 [HandleError]过滤器?
我在 Web.config 文件中设置 customError

<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 ()。 Visual Studio 在出现错误时停止,按下 f5继续后,我被重新路由到 Error.aspx? aspxerrorpath =/sxi.mvc/CrashTest (其中 sxi 是所用控制器的名称)。 当然,路径无法找到,我得到“服务器错误在’/’应用程序。”404。

这个站点是从预览3移植到5的。 除了错误处理之外,所有东西都可以运行(移植的工作量不大)。 当我创建一个完整的新项目时,错误处理似乎可以正常工作。

有什么想法吗?

——注意——
由于这个问题现在有超过3K 的视图,我认为它将是有益的,把我目前使用的(ASP.NET MVC 1.0)。 在 Mvc 贡献项目中有一个很棒的属性叫做“ RescueAttribute” 你可能也应该去看看;)

101612 次浏览

You are missing Error.aspx :) In preview 5, this is located in your Views/Shared folder. Just copy it over from a new Preview 5 project.

[HandleError]

When you provide only the HandleError attribute to your class (or to your action method for that matter), then when an unhandled exception occurs MVC will look for a corresponding View named "Error" first in the Controller's View folder. If it can't find it there then it will proceed to look in the Shared View folder (which should have an Error.aspx file in it by default)

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

You can also stack up additional attributes with specific information about the type of exception you are looking for. At that point, you can direct the Error to a specific view other than the default "Error" view.

For more information, take a look at Scott Guthrie's blog post about it.

It should also be noted that errors that don't set the http error code to 500

(e.g. UnauthorizedAccessException)

will not be handled by the HandleError filter.

Solution for http error code to 500 this is an attribute called [ERROR] put it on an action

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


}

//EXAMPLE:

[Error]
[HandleError]
[PopulateSiteMap(SiteMapName="Mifel1", ViewDataKey="Mifel1")]
public class ApplicationController : Controller
{
}
    [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();
}

}

Attributes in MVC is very useful in error handling at get and post method, it also track for ajax call.

Create a base controller in your application and inherit it in your main controller(EmployeeController).

public class EmployeeController : BaseController

Add below code in base controller.

/// <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

Add below code:

/// <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:

Call CheckAJAXError function in layout page load.

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