I have an ASP.NET MVC 5 application and I set up the session state using SQL Server. Everything works fine.
I am currently on my developer server, so I thought to disconnect the internet [the session db is online], to see what happens. Not surprisingly the famous yellow page of death occurred. Then I thought to catch this exception and I used :
try{
session["age"]= 25;
}catch
{ //log the exception here and continue}
but I was surprised that this will not cause any exception here; because the application will not contact the SQL Server at this stage.
It seems that when the IIS prepared the view page to show the user; it then contact the SQL Server to save the session information and if failed then it will throw that yellow page of death.
My question is:
is there any way to catch the exception in the code? Other than in Global.asax?
Session load/access happens at the beginning of the request lifecycle (HttpApplication.AcquireRequestState Event) and persisted back at the end of the request lifecycle (HttpApplication.ReleaseRequestState Event). It is not at the point where you'd get a value out of the session. To catch it, use an MVC Global Action Filter to handle exceptions, including the SQLException which will occur when this is the case. Alternatively, create an HttpModule to handle exception events.
In your RegisterGlobalFilters method (which is called by Global.asax.cs):
public class FilterConfig
{
public static void RegisterGlobalFilters( GlobalFilterCollection filters )
{
filters.Add( new YourCustomExceptionHandlingAttribute } );
}
}
And YourCustomExceptionHandlingAttribute should implement HandleErrorAttribute
Related
In asp.net application, all the exception that occurs and are not inside try catch can be handled by application_error.
If we just need to log the exception along with its stack trace, and we need not make any other decision/logic inside catch, why should we put try catch at application/bl or dal layer functions? Is there any reason to put try/catch with every database call function?
For example we have hundreds of function in DAL layer that executes following code:
try
{
//open db connection, execute stored procedure
}
catch
{
//log error
}
In case we get any exception from stored procedure OR in opening database connection, we get an exception but we are not doing anything except for logging these errors. We don't have very critical data-storage/retrieval requirement. We are logging error just to be alerted and fix it later. Is this correct to put catch in every such function?
Using try and catch is not for logging purposes only, especially when dealing with database connections.
An exception means that something wasn't completed. If something wasn't completed, your business process failed. If your business process failed, you need to know about it and handle it within the scope of that code, not application_error. Each error should be handled within the scope it was generated from. application_error should be your last fallback, and theoretically should never be reached.
Sure, you can use it for logging, but also for closing your DB connection (which was probably opened before the exception occurred and be left forever open), informing your users that an exception occured, and for data recovery, alternating your process to deal with the exception or preparing it for a retry.
So, taking your posted template, good code handling should look like this:
try
{
//open db connection, execute stored procedure
}
catch
{
// Inform the user
// Alternate your process or preparing for retry
// log error
}
finally
{
// Close the DB connection
}
One should use try/catch blocks only in places where you can meaningfully handle an exception. However, "meaningful handling " includes providing good error messages.
If your catch block simply logs the exception with no additional context, then such block could be replaced with a top-level handler (like application_error) that does the same thing.
If, however, you log additional information available only at the point of invocation, then having a catch block is entirely justified: it enhances the experience by providing better diagnostics, which is a perfectly legitimate goal.
I have an MVC Razor application that uses entity framework 6.0. However, if the DB is down or something, my code starts throwing exceptions at all kinds of random places like when I start evaluating my IEnumerable<T>s and IQueryable<T>s.
The model constructor is generated code that will be overwritten if I modify it which wouldn't help anyway because the constructor doesn't throw exceptions. Instead, the exceptions come in places like this
using (var dataContext = new ArchiveVMADDatabase.ArchiveDatabaseModel())
{
IQueryable<HDeploy> deploys = Helpers.GetProdDeploysFromArchive(dataContext);
var query = getBranchSelectListQuery(deploys);
listItems.AddRange(query);// EXCEPTION IF DB IS DOWN
}
Is there a good way for me to handle this in one place and avoid wrapping nearly 100% of my code in giant try catch blocks? I would really like to have it just return empty sets if it can't talk to the DB.
I'm not sure whether you are working with MVC or Web API, but in Web API one would use Exception Filters to centralize exception handling.
An exception filter is basically a derivative of the ExceptionFilterAttribute that can create a specific response depending on the caught exception:
public class NotImplExceptionFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is NotImplementedException)
{
context.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);
}
}
}
You don't need to add try {} catch {} blocks anywhere -- Web API triggers the configured exception filters automatically as soon as an exception reaches the outer most layer of your system (i.e. the controller level).
You can activate an exception filter only for specific ApiControllers or globally for every controller.
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
}
I am writing an ASP.NET application in C# and I am working on handling possible exceptions that may be thrown from another file. I have a C# class file that I wrote containing methods that execute SQL commands, and I want to protect against possible exceptions being thrown once my application goes into production.
This is the SQL method I wrote that I am intentionally throwing an error in (From SqlData.cs):
public SqlConnection openConnection()
{
//Create an SQL connection
SqlConnection myConnection = new SqlConnection("My intentionally incorrect connection string");
//Open the connection
try
{
myConnection.Open();
}
catch (SqlException myAppEx)
{
throw new ApplicationException("There was an error opening the SQL database connection", myAppEx);
}
return myConnection;
}
I call this method from my Default.aspx.cs file with the following lines of code:
try
{
//The ReadDT method calls openConnection() in itself
dt = sqlData.ReadDT(query);
}
catch (ApplicationException exc)
{
throw exc;
}
I am trying to implement Page level exception handling, where if an exception is raised on the current page the Page_Error method is supposed to be called, as cited here. This is why I catch the exception that was thrown from my SqlData.cs class file, and re-throw the exception, so that this exception is seen by the server. Hence, Server.GetLastError() will not return null.
As implemented here, I have a separate error page that displays all of the information on the exception. My Page_Error method is as follows:
private void Page_Error(object sender, EventArgs e)
{
Server.Transfer("ErrorPage.aspx?handler=Page_Error%20-%20Default.aspx", true);
}
From here the user is redirected to my ErrorPage.aspx and the SqlException that was originally thrown is displayed perfectly.
The problem - When I catch the exception from the SqlData.cs, and re-throw the exception, an UnhandledException is raised. if I do not put a try catch block around the ReadDT method call, the same UnhandledException is raised from my SqlData.cs file.
Code trace:
throw new ApplicationException("There was an error opening the SQL database connection", myAppEx); (This works correctly)
The exception is then caught and re-thrown (UnhandledException occurs)
The Page_Error method is called as it should be and everything executes properly!
I hope I have been clear in answering myself, I have done a lot of research on exceptions and my particular problem and I have not had any success in finding an answer.
Thanks,
Eric
In ASP.NET, unhandled exceptions thrown by your application will be wrapped in an HttpUnhandledException before calling the Page or Global error handler. You need to look at its InnerException property to get at the original exception.
In general, you shouldn't bother wrapping and rethrowing exceptions like you're doing unless you're adding value (for example, additional data regarding the context of the exception). Just let them propagage to wherever they're eventually handled (Page_Error in your case, though you might consider using Application_Error in global.asax.cs, to avoid repeating this error handling code on every page).
So I came up with a combination of error handling through Code Level exception handling, and redirecting the user to an error page, then logging the error with ELMAH, to solve my problem.
I now handle all exception's directly in my SqlData class file, for the least yet most efficient code. I have a global variable HttpResponse response in my SqlData class file, that I populate each time I create a new instance of the class from within my ASP.NET application. So from my Main.aspx.cs file I have something like:
private SQLData data;
protected void Page_Load(object sender, EventArgs e)
{
data = new SQLData(Response);
...
}
If I do this I am able to call a response.Redirect() from my class file to send the user to my error page, I pass the exception error message and type of exception in a query string, to which I then print out to the user in my error page. This allows me to display only non-sensitive information to the user. Therefore the exception has been handled and ELMAH has logged all of the specifics!
//Create an SQL connection
SqlConnection myConnection = new SqlConnection("MyConnString");
//Open the connection
try
{
myConnection.Open();
}
catch (Exception ex)
{
//Manually log the exception in ELMAH
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
//Redirect the user to the error page
response.Redirect("ErrorPage.aspx?ErrorMessage=" + ex.Message + "&ErrorType=SQLException", true);
}
return myConnection;
I then have a link display at the bottom of my error page directing to the elamh.axd page only if you are an administrator. From this page you may view the stack trace and other sensitive information.
You can find information on ELMAH at the bottom of this page as well as setting up ELMAH in an ASP.NET application. It is very easy to do, and a very powerful tool.
Cheers,
Eric
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
{
}