How to catch unhandled errors in ASP.NET MVC? - asp.net-mvc

I've created a simple MVC project, add one method:
public class HomeController : Controller
{
public async Task<string> Index()
{
var t = Task.Run(() =>
{
Debug.Print("Debug___1");
throw new Exception("Error #1");
Debug.Print("Debug___2");
});
await Task.Delay(5000);
return "ASD";
}
}
Then i run application, get "ASD" output and debug messages:
Debug___1
Exception thrown: 'System.Exception' in WebApplication2.dll
But how can I catch that exception? I've tried creating Application_Error method on global.asas, but it didn't work:
namespace WebApplication2
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
protected void Application_Error(object sender, EventArgs e)
{
Debug.Print("Catched");
}
}
}

At the controller level, you can deal with unhandled exceptions by overriding the OnException method.
Look at this link for a description: https://www.codeproject.com/Articles/850062/Exception-handling-in-ASP-NET-MVC-methods-explaine

catch(Exception ex)
{
//create custom error handling method
ErrorLog(ex);
}
Public static void Errorlog(Exception ex)
{
//creates new txt file to view errordetails
string strPath = #"D:\ErrorLog.txt";
File.create(strPath);
using (StreamWriter sw = File.AppendText(strPath))
{
sw.WriteLine("Error Details",+DateTime.Now);
sw.WriteLine("Error Message: " + ex.Message);
sw.WriteLine("Stack Trace: " + ex.StackTrace);
}
}

.NET 4 allows you to define how your task will handle exceptions as shown in the following post : catch exception that is thrown in different thread
So in your example above, you would first define your task
Task<string> task = new Task<string>(Test);
then pass in an exception handler
task.ContinueWith(ExceptionHandler, TaskContinuationOptions.OnlyOnFaulted);
then finally define an exception handler somewhere
static void ExceptionHandler(Task<string> task)
{
var exception = task.Exception;
//Handle error via ModelState or how you prefer
}

Use the HttpServerUtility.HttpApplication.Server object's method GetLastError.
protected void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
}

Related

Error handling last chance to catch View Rendering exception

I've got ErrorController which customly handles my website errors.
It's pretty standard:
public class ErrorController : BaseController
{
public ActionResult Error404(Exception ex)
{
return View();
}
public ActionResult Error500(Exception ex)
{
return View();
}
}
However, in case if some rendering exception occurs inside of the View code (and this might occur, as the page has Master page (master layout) and different might happen), then I am not able to catch that rendering exception.
I can really see that exception with implementing ActionFilterAttribute.OnResultExecuted:
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
if (filterContext.Exception != null)
{
// not sure what to do here
} else base.OnResultExecuted(filterContext);
}
but in that case MVC looks for ~/Shared/Error.cshtml (incl. this path) after that exception occurs, and I can't provide the Errors view rendering exception to the user -- the "Last chance exception".
Is there any way to handle that?
Here is a nice article on Exception handling in ASP.Net MVC that should help
Method 4:- Inheriting from “HandleErrorAttribute”
public class CustomHandleErrorAttribute: HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
Exception ex = filterContext.Exception;
filterContext.ExceptionHandled = true;
var model = new HandleErrorInfo(filterContext.Exception, "Controller", "Action");
filterContext.Result = new ViewResult()
{
ViewName = "Error",
ViewData = new ViewDataDictionary(model)
};
}
}
And you attach that to your base controller.

How can i catch parameter on maproute?

How can i retrieve certain a section on routemap pattern.For instance i have a routemap pattern on my config file as routes.MapRoute("", "Post/{slug}", new { controller = "Post", action = "Index" }) and i want to catch slug parameter inside global.asax.I tried as followed but it returns null.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
var context = base.Context;
if (context != null)
{
Response.Write(context.Request.RequestContext.RouteData.Values["slug"]);
}
}
You can try this:
protected void Application_BeginRequest(object sender, EventArgs e)
{
var httpContext = ((MvcApplication)sender).Context;
var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
if (currentRouteData.Values["slug"] != null)
{
Response.Write(currentRouteData.Values["slug"]);
}
}
I believe RouteData is not yet resolved when BeginRequest event is fired. You can use EndRequest instead.
protected void Application_EndRequest(object sender, EventArgs e)
{
var context = base.Context;
if (context != null)
{
Response.Write(context.Request.RequestContext.RouteData.Values["slug"]);
}
}
To make sure correct route is being used and slug parameter is actually supplied I'd recommend Route debugger

Global.asax in Umbraco 6

I had the following in my Global.asax (Umbraco 4.7)
Application_Start
Application_EndRequest
Application_Error
Session_Start
Session_End
Now I have upgraded to Umbraco 6.0.3, which global.asax inherits from Umbraco.Web.UmbracoApplication
Where do I put my event handlers (and what are the equivalent method names)?
This is what I found so far.
You can create your own class
public class Global : Umbraco.Web.UmbracoApplication
{
public void Init(HttpApplication application)
{
application.PreRequestHandlerExecute += new EventHandler(application_PreRequestHandlerExecute);
application.EndRequest += (new EventHandler(this.Application_EndRequest));
//application.Error += new EventHandler(Application_Error); // Overriding this below
}
protected override void OnApplicationStarted(object sender, EventArgs e)
{
base.OnApplicationStarted(sender, e);
// Your code here
}
private void application_PreRequestHandlerExecute(object sender, EventArgs e)
{
try
{
if (Session != null && Session.IsNewSession)
{
// Your code here
}
}
catch(Exception ex) { }
}
private void Application_BeginRequest(object sender, EventArgs e)
{
try { UmbracoFunctions.RenderCustomTree(typeof(CustomTree_Manage), "manage"); }
catch { }
}
private void Application_EndRequest(object sender, EventArgs e)
{
// Your code here
}
protected new void Application_Error(object sender, EventArgs e)
{
// Your error handling here
}
}
And have Global.asax inherit from your class
<%# Application Codebehind="Global.asax.cs" Inherits="Global" Language="C#" %>
Alternative method: Inherit ApplicationEventHandler - but it's not working for me

MVC 4 Global Exception Filter how to implement?

How do I implement a global exception handler in MVC4 as it seems to be different from MVC3.
Not sure how to implement the following:
public class ErrorHandlerAttribute: System.Web.Mvc.FilterAttribute,
IExceptionFilter
{
public Task ExecuteExceptionFilterAsync(
HttpActionExecutedContext actionExecutedContext,
CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
Unfortunately the link provided in Eric Leschinski's commet only shows how to implement the System.Web.Mvc.IExceptionFilter interface, and not the System.Web.Http.Filters.IExceptionFilter interface. The first is used in regular MVC controllers, while the second targets ApiCotrollers.
Here is a simple class example I came up with for logging unhandled exceptions thrown in my ApiControllers:
public class ExceptionLoggerFilter: IExceptionFilter
{
public ExceptionLoggerFilter(Logger logger)
{
this.logger = logger;
}
public bool AllowMultiple { get { return true; } }
public Task ExecuteExceptionFilterAsync(
HttpActionExecutedContext actionExecutedContext,
CancellationToken cancellationToken)
{
return Task.Factory.StartNew(() =>
{
logger.Error("web service error", actionExecutedContext.Exception);
}, cancellationToken);
}
private Logger logger;
}
And all you have to do to enable this filter is register it in yours Global.asax Application_Start method:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
// allocate filter and add it to global configuration
var exceptionLogger = new ExceptionLoggerFilter(Container.Get<Logger>());
GlobalConfiguration.Configuration.Filters.Add(exceptionLogger);
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
I hope this helps other googlers out there!
The way I created an exception handler for MVC part of it, I created a class that implemented IExceptionFilter
public class MVCExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
Trace.TraceError(filterContext.Exception.ToString());
}
}
You then register it in the Global.asax.cs
inside protected void Application_Start()
The method already contains the line
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
So, you will need to add this line ABOVE it
GlobalFilters.Filters.Add(new MVCExceptionFilter());

replacement for try catch(MyEx ex) in each action

I need something that would work like this:
public ActionResult Ac()
{
try {
//stuff...
}
catch(MyException ex)
{
//handle
}
}
but without putting try catch in each action method
You want to annotate your classes with HandleErrorAttribute - http://msdn.microsoft.com/en-us/library/system.web.mvc.handleerrorattribute.aspx.
If the functionality of the built in handler above isn't sufficient then you can define your own class which implements IExceptionFilter - the OnException method takes an ExceptionContext object with Result and HttpContext properties you can use to control the outcome, something like:
public class MyHandleErrorAttribute : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
Exception e = filterContext.Exception;
// Do some logging etc. here
if (!filterContext.ExceptionHandled && filterContext.HttpContext.IsCustomErrorEnabled)
{
ViewResult lResult = ...
filterContext.Result = lResult;
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.StatusCode = 500;
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
}
}
Use Exception Filters for exception handling.
How about
[HandleError(ExceptionType = typeof(MyException ), View = "MyErrView"))]
public ActionResult Ac()
{
//stuff
}
but with a custom HandleError Attribute that handles the type of exceptions you are targeting. This SO question should give you a good start.

Resources