I got many Actions in my controller. Is there any way to try-catch whole Controller-document once instead inserting try-catch in every single action?
you could override the OnException method
protected override void OnException(ExceptionContext filterContext)
{
//your handling logic here
filterContext.ExceptionHandled = true;
}
Yes, you can capture the Application_Error event, which will handle all exceptions that are not handled by a the action code. For more information see this article.
If you want to catch any exception in all controllers in your MVC Application, then go for Global Exception Filters, this is a link that explains exactly how to catch and log global exceptions into database
http://www.dotnetcurry.com/aspnet-mvc/1260/exception-handling-logging-aspnet-mvc
Related
I setup an exception handling class to log errors to the database which works really well but I was wondering if I can also somehow setup the application so any error outside of a try catch will call the same procedure somehow?
It works well most of the time and shows a screen with an error code to the user but I want to be able to use this friendly error screen each time but on the odd occasion an error outside of the try catch is thrown and it shows the normal asp.net error.
The catch I use:
catch (SqlException ex)
{
ExceptionHandling.SQLException(ex, constPageID, constIsSiteSpecific);
}
It is possible to use the Global.asax's Application_Error method.
protected void Application_Error()
{
Exception exception = Server.GetLastError();//Get the Last Error
LogException(exception);//Custom Code
}
However be aware that if you do any error a user suffers will direct them onto your error page. It's often better to handle smaller errors on the page itself and present a simple message.
There are countless discussions on proper error handling - personally I like to catch everything the UI method which called it (OnPreRender, OnLoad OnEvent etc).
If you are developing an ASP.NET application, you can log unhandled exceptions in Global.asax in "Application_Error" method.
protected void Application_Error()
{
Exception exception = Server.GetLastError();
// Clear the error
Server.ClearError();
// Log exception
}
Suppose I have A CustomAuthorizeAttribute and I thew Exception in HandleUnauthorizedRequest. Is there any way to catch that exception and format the message and display it to the user. If not than how should a thing like this be implemented.
Do you want to do this globally? Or on a per controller basis?
If Globally, then you can create your own HandleErrorAttribute which will catch any unhandled exceptions. You can then test if the exception is HandleUnauthorizedRequest or not.
If you want to do this on a per controller basis, then you can override OnException and handle it there.
When an exception is thrown by your own code that's called from an action in a controller how should that be handled? I see a lot of examples of best practices where there are no try-catch statements at all. For example, accessing data from a repository:
public ViewResult Index()
{
IList<CustomModel> customModels = _customModelRepository.GetAll();
return View(customModels);
}
Clearly this code could throw an exception if the call is to a database that it can't access and we are using an ORM like Entity Framework for example.
However all that I can see will happen is that the exception will bubble up and show a nasty error message to the user.
I'm aware of the HandleError attribute but I understand it's mostly used to redirect you to an error page if an exception that's unhandled occurs.
Of course, this code could be wrapped in a try-catch but doesn't separate nicely, especially if you have more logic:
public ViewResult Index()
{
if (ValidationCheck())
{
IList<CustomModel> customModels = new List<CustomModel>();
try
{
customModels = _customModelRepository.GetAll();
}
catch (SqlException ex)
{
// Handle exception
}
if (CustomModelsAreValid(customModels))
// Do something
else
// Do something else
}
return View();
}
Previously I have extracted out all code that could throw exceptions like database calls into a DataProvider class which handles errors and returns messages back for showing messages to the user.
I was wondering what the best way of handling this is? I don't always want to return to an error page because some exceptions shouldn't do that. Instead, an error message to the user should be displayed with a normal view. Was my previous method correct or is there a better solution?
I do three things to display more user-friendly messages:
Take advantage of the global exception handler. In the case of MVC: Application_Error in Global.asax. Learn how to use it here: http://msdn.microsoft.com/en-us/library/24395wz3(v=vs.100).aspx
I subclass Exception into a UserFriendlyException. I do my very best in all of my underlying service classes to throw this UserFriendlyException instead of a plain old Exception. I always try to put user-meaningful messages in these custom exceptions. The main purpose of which is to be able to do a type check on the exception in the Application_Error method. For the UserFriendlyExceptions, I just use the user-friendly message that I've set deep down in my services, like "Hey! 91 degrees is not a valid latitude value!". If it's a regular exception, then it's some case I haven't handled, so I display a more generic error message, like "Oops, something went wrong! We'll do our best to get that fixed!".
I also create an ErrorController that is responsible for rendering user-friendly views or JSON. This is the controller whose methods will be called from the Application_Error method.
EDIT:
I thought I'd give a mention to ASP.NET Web API since it's closely related. Because the consumer of Web API endpoints won't necessarily be a browser, I like to deal with errors a little differently. I still use the "FriendlyException" (#2 above), but instead of redirecting to an ErrorController, I just let all my endpoints return some kind of base type that contains an Error property. So, if an exception bubbles all the way up to the Web API controllers, I make sure to stick that error in the Error property of API response. This error message will either be the friendly message that has bubbled up from the classes the API controller relies on, or it will be a generic message if the exception type is not a FriendlyException. That way, the consuming client can simply check whether or not the Error property of the API response is empty. Display a message if the error is present, proceed as usual if not. The nice thing is that, because of the friendly message concept, the message may be much more meaningful to the user than a generic "Error!" message. I use this strategy when writing mobile apps with Xamarin, where I can share my C# types between my web services and my iOS/Android app.
With Asp.Net MVC you can also override the OnException method for you controller.
protected override void OnException(ExceptionContext filterContext)
{
if (filterContext.ExceptionHandled)
{
return;
}
filterContext.Result = new ViewResult
{
ViewName = ...
};
filterContext.ExceptionHandled = true;
}
This allow you to redirect to a custom error page with a message that refer to the exception if you want to.
I used an OnException override because I have several projects referenes to one that have a Controller that handle errors:
Security/HandleErrorsController.cs
protected override void OnException(ExceptionContext filterContext)
{
MyLogger.Error(filterContext.Exception); //method for log in EventViewer
if (filterContext.ExceptionHandled)
return;
filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
filterContext.Result = new JsonResult
{
Data = new
{
Success = false,
Error = "Please report to admin.",
ErrorText = filterContext.Exception.Message,
Stack = filterContext.Exception.StackTrace
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
filterContext.ExceptionHandled = true;
}
All questions like this are not very constructive, because the answer is always "it depends", because there are so many ways of dealing with error handling.
Many people like to use the HandleError method, because any exception is basically non-recoverable. I mean, what are you going to do if you can't return the objects? You're going to show them an error anyways, right?
The question becomes, how you want to show them the error. If showing them an error page is acceptable, than HandleError works fine, and provides an easy place to log the error. If you're using Ajax or want something fancier, then you need to develop a way to do that.
You talk about a DataProvider class. That's basically what your Repository is. Why not build that into your repository?
I realize this is a shot in the dark and not the best practice or way of going about it, but I want to do specific logging information as the exception is thrown. It is important that the state of the web form does not change.
You can use
try
{
}
catch(Exception ex)
{
//your treatment does not contain throw ex.
//mute exception in order to not change state
}
You can use this in your webform or in your gloabl.asax in Application_Error (in order to centralize exception treatment)
try
{
ExceptionProneCode()
}
catch(Exception ex)
{
WriteToSomeLogFile(ex.Message);
//if you want the exception to bubble up from this point,
//than you would type "throw;"
}
If we are talking in the context of ASP.NET, the Application_Error event would be a good place to put a global exception logging block.
I have a website built in C#.NET that tends to produce a fairly steady stream of SQL timeouts from various user controls and I want to easily pop some code in to catch all unhandled exceptions and send them to something that can log them and display a friendly message to the user.
How do I, through minimal effort, catch all unhandled exceptions?
this question seems to say it's impossible, but that doesn't make sense to me (and it's about .NET 1.1 in windows apps):
All unhandled exceptions finally passed through Application_Error in global.asax. So, to give general exception message or do logging operations, see Application_Error.
If you need to catch exeptions in all threads the best aproach is to implement UnhandledExceptionModule and add it to you application look here
for an example
Use the Application_Error method in your Global.asax file. Inside your Application_Error method implementation call Server.GetLastError(), log the details of the exception returned by Server.GetLastError() however you wish.
e.g.
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
log4net.ILog log = log4net.LogManager.GetLogger(typeof(object));
using (log4net.NDC.Push(this.User.Identity.Name))
{
log.Fatal("Unhandled Exception", Server.GetLastError());
}
}
Don't pay too much attention to the log4net stuff, Server.GetLastError() is the most useful bit, log the details however you prefer.
The ELMAH project sounds worth a try, its list of features include:
ELMAH (Error Logging Modules and
Handlers) is an application-wide error
logging facility that is completely
pluggable. It can be dynamically added
to a running ASP.NET web application,
or even all ASP.NET web applications
on a machine, without any need for
re-compilation or re-deployment.
Logging of nearly all unhandled exceptions.
A web page to remotely view the entire log of recoded exceptions.
A web page to remotely view the full details of any one logged
exception.
In many cases, you can review the original yellow screen of death that
ASP.NET generated for a given
exception, even with customErrors mode
turned off.
An e-mail notification of each error at the time it occurs.
An RSS feed of the last 15 errors from the log.
A number of backing storage implementations for the log
More on using ELMAH from dotnetslackers
You can subscribe to the AppDomain.CurrentDomain.UnhandledException event.
It's probably important to note that you are not supposed to catch unhandled exceptions. If you are having SQL timeout issues, you should specifically catch those.
Do you mean handling it in all threads, including ones created by third-party code? Within "known" threads just catch Exception at the top of the stack.
I'd recommend looking at log4net and seeing if that's suitable for the logging part of the question.
If using .net 2.0 framework, I use the built in Health Monitoring services. There's a nice article describing this method here: https://web.archive.org/web/20210305134220/https://aspnet.4guysfromrolla.com/articles/031407-1.aspx
If you're stuck with the 1.0 framework, I would use ELMAH:
http://msdn.microsoft.com/en-us/library/aa479332.aspx
hope this helps
There are 2 parts to this problem handling & identifying.
Identifying
This is what you do when the exception is finally caught, not necessarily where it is thrown. So the exception at that stage must have enough context information for you to idenitfy what the problem was
Handling
For handling, you can
a) add a HttpModeule. See
http://www.eggheadcafe.com/articles/20060305.asp
I would suggest this approach only when there is absolutely no context informaatn available and there might be issuus wiih IIS/aspnet, In short for catastrophic situations
b) Create a abstract class called AbstractBasePage which derives from Page class and have all your codebehind classes derive from AbstractBasePage
The AbstractBasePage can implement that Page.Error delegate so that all exceptions which percolate up through the n-tier architecture can be caught here(and possibly logged)
I would suggest this cause for the kind of exceptions you are talking about (SQlException) there is enough context information for you to identify that it was a timeout and take possible action. This action might include redirecting user to a custom error page with appropriate message for each different kind of exception (Sql, webservice, async call timeouts etc).
Thanks
RVZ
One short answer is to use (Anonymous) delegate methods with common handling code when the delegate is invoked.
Background: If you have targeted the weak points, or have some boilerplate error handling code you need to universally apply to a particular class of problem, and you don't want to write the same try..catch for every invocation location, (such as updating a specific control on every page, etc).
Case study: A pain point is web forms and saving data to the database. We have a control that displays the saved status to the user, and we wanted to have common error handling code as well as common display without copy-pasting-reuse in every page. Also, each page did it's own thing in it's own way, so the only really common part of the code was the error handling and display.
Now, before being slammed, this is no replacement for a data-access layer and data access code. That's all still assumed to exist, good n-tier separation, etc. This code is UI-layer specific to allow us to write clean UI code and not repeat ourselves. We're big believers in not quashing exceptions, but certain exceptions shouldn't necessitate the user getting a generic error page and losing their work. There will be sql timeouts, servers go down, deadlocks, etc.
A Solution: The way we did it was to pass an anonymous delegate to a method on a custom control and essentially inject the try block using anonymous delegates.
// normal form code.
private void Save()
{
// you can do stuff before and after. normal scoping rules apply
saveControl.InvokeSave(
delegate
{
// everywhere the save control is used, this code is different
// but the class of errors and the stage we are catching them at
// is the same
DataContext.SomeStoredProcedure();
DataContext.SomeOtherStoredProcedure();
DataContext.SubmitChanges();
});
}
The SaveControl itself has the method like:
public delegate void SaveControlDelegate();
public void InvokeSave(SaveControlDelegate saveControlDelegate)
{
// I've changed the code from our code.
// You'll have to make up your own logic.
// this just gives an idea of common handling.
retryButton.Visible = false;
try
{
saveControlDelegate.Invoke();
}
catch (SqlTimeoutException ex)
{
// perform other logic here.
statusLabel.Text = "The server took too long to respond.";
retryButton.Visible = true;
LogSqlTimeoutOnSave(ex);
}
// catch other exceptions as necessary. i.e.
// detect deadlocks
catch (Exception ex)
{
statusLabel.Text = "An unknown Error occurred";
LogGenericExceptionOnSave(ex);
}
SetSavedStatus();
}
There are other ways to achieve this (e.g. common base class, intefaces), but in our case this had the best fit.
This isn't a replacement to a great tool such as Elmah for logging all unhandled exceptions. This is a targeted approach to handling certain exceptions in a standard manner.
Timeout errors typically occur if you are not forcefully closing your sqlconnections.
so if you had a
try {
conn.Open();
cmd.ExecuteReader();
conn.Close();
} catch (SqlException ex) {
//do whatever
}
If anything goes wrong with that ExecuteReader your connection will not be closed. Always add a finally block.
try {
conn.Open();
cmd.ExecuteReader();
conn.Close();
} catch (SqlException ex) {
//do whatever
} finally {
if(conn.State != ConnectionState.Closed)
conn.Close();
}
This is old question, but the best method (for me) is not listed here. So here we are:
ExceptionFilterAttribute is nice and easy solution for me. Source: http://weblogs.asp.net/fredriknormen/asp-net-web-api-exception-handling.
public class ExceptionHandlingAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
var exception = context.Exception;
if(exception is SqlTimeoutException)
{
//do some handling for this type of exception
}
}
}
And attach it to f.e. HomeController:
[ExceptionHandling]
public class HomeController: Controller
{
}