I have an ASP.NET MVC 4 web application that retrieves data from a data source via WCF services.
I have set up most of controllers to be Async
and subsequent methods to be Task
based.
I have encountered a problem though. If an exception occurs in my code, the page being loaded just continues to load and in the end times-out with the IIS error page showing.
I have a friendly error message set up and works fine for sync
actions but not async
ones. The action just keeps running even though an exception may have occurred at a different level. I tried applying the AsyncTimeout
attribute to the controller action but no luck, page just keeps loading for a long period of time.
Any ideas how I could handle this in my code, preferably at a global type level and direct the user to an error page when an issue occurs with an async
controller action?
Set customErrors to On or RemoteOnly in Web.config
<system.web>
<customErrors mode="On" />
</system.web>
Use HandleErrorAttribute with custom error view
[AsyncTimeout(1000)]
[HandleError(ExceptionType=typeof(System.TimeoutException), View="Timeout")]
public async Task<ActionResult> AsyncActionResultReport()
{
Override the OnException Method of your Async Controller, or use a custom Exception Attribute
public override void OnException(ExceptionContext filterContext)
{
if(filterContext.Exception is TimeoutException && filterContext.Controller is AsyncController)
{
filterContext.HttpContext.Response.StatusCode = 200;
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary {
{ "Controller", "Home" },
{ "Action", "TimeoutRedirect" }
filterContext.ExceptionHandled = true;
}
base.OnException(filterContext);
}
If you want to do controller level, the HandleError
as suggested by Dave A is perfect. But for applying HandleError Attribute at Global Level you have to use ExceptionFilter.
You can also apply the HandleError
Attribute for the entire application by registering it as a global error handler. For registering a global error handler, open the FilterConfig.cs
file with in App_Start
folder to find the RegisterGlobalFilters
method.
By default, ASP.NET MVC template has already registered a global HandleErrorAttribute
to the GlobalFilterCollection
for your application. Here you can also add your own custom filter to the global filter collection as well like :
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute
{
ExceptionType = typeof(System.TimeoutException),
View = "TimeoutExceptionView"
});
filters.Add(new HandleErrorAttribute()); //by default added
}
For details refer:
http://www.dotnet-tricks.com/Tutorial/mvc/19D9140313-Exception-or-Error-Handling-and-Logging-in-MVC4.html
OR
Alternatively you can use Application_Error
(NOT Recommended) to catch exception & redirect to required action like:
protected void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
System.Diagnostics.Debug.WriteLine(exception);
if (exc.GetType() == typeof(TimeoutException)
{
Response.Redirect("/Home/ErrorView");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With