Can ASP.NET's System.web.Management be used for logging events like user logins, password changes and access to certain resources? Should system.Web.Management be used for logging of errors and health monitoring instead?
I want to log events without re-inventing the whole thing. I know ELMAH is used for errors; can it be used for logging events too?
From the article ELMAH - Error Logging Modules And Handlers on the now defunct DoNetSlackers:
Error signaling is exposed via the ErrorSignal class, which provides a single overloaded method called Raise. Simply put, exceptions raised via the ErrorSignal class are not thrown, therefore they don't bubble up, but instead are only sent out to ELMAH, as well as to whomever subscribes to the Raise event of the ErrorSignal class.
The code snippet below shows how to obtain an instance of the ErrorSignal class, which is unique per application and can be retrieved simply with the static FromCurrentContext method, and then use it to signal an exception.
ErrorSignal.FromCurrentContext().Raise(new NotSupportedException());
The difference between signaling and throwing an exception is that in the first case no one will ever know about the error except ELMAH.
Further Reading:
How to get ELMAH to work with ASP.NET MVC [HandleError] attribute?
Related
I have an MVC+SignalR application that has a lot of Reactive Extensions subscriptions flying around, all of which are projections of data coming from a Socket in realtime. Some of these subscriptions are not working as expected, and when they raise an exception it just goes into the void unless I'm debugging.
I had hoped that I could use Elmah to automatically log these unhandled exceptions, but it seems that unless the exception occurs on the same thread that's processing the request/response, eg it causes a yellow screen of death, Elmah isn't touching it. So my question is twofold:
Can I get Elmah to automatically log exceptions on background/worker processes?
If the answer to #1 is "no", what's my next best option, other than wrapping my subscriptions in try/catch blocks at a very high level?
Ad 1) If it doesn't happen already it probably doesn't.
I don't know how exactly you use background threads, but I will try to explain were ELMAH handling is working. ELMAH is integrated into ASP.NET pipeline, and when the error occurs it is handled by ASP.NET pipeline, which shows error page (like http error 500) and invoke ErrorLogModule. Moreover quoting Using HTTP Modules and Handlers to Create Pluggable ASP.NET Components -> Adding ELMAH to an ASP.NET Web Application
The section adds the ErrorLogModule HTTP module to the
ASP.NET HTTP pipeline. Make sure you include this
setting, otherwise ELMAH won't be listening for the Error event, and
therefore won't be logging any unhandled exceptions.
Ad 2) Because you are using Reactive Extensions you can handle onError in which you can automatically log into Elmah. If you don't want to writer everywhere error hangling in OnError, just create your own function or method extension which will wrap it automatically for you. Writing into ELMAH manually is simple just call:
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
In my ASP.NET MVC3 application I want all unexpected problems logged. So I have logging inside Application_Error(). Also I found there's Controller.OnException() method and so I made an override for my controllers that log the error and then call base.OnException().
Looks like every time an exception occurs in a controller action my OnException() override is called and then Application_Error() is called and so logging is performed twice.
If I eliminate my OnException() override and only leave logging in Application_Error() will I still log all the problems or will I miss any kind of events?
Controller.OnException() is MVC specific. Application_Error() is ASP.NET specific. MVC sits on top of ASP.NET, so if you handle the exception in Controller.OnException(), you may want to set ExceptionContext's ExceptionHandled to true so that it doesn't propagate down the pipeline into Application_Error().
You're right in that every error can be allowed to propagate to the Application_Error() level and handled there. It really depends on choice and preference I think. I see it both ways. I see the benefit in handling action method specific errors in Controller's OnException and other errors when the request does not even reach the controller (e.g. start-up errors, 404s) in Application_Error. When you have a hybrid app that uses both MVC and web forms, then Application_Error has to be used for web forms errors.
So while handling exceptions in Application_Error() is a must-have for making sure your app doesn't have uncaught exceptions, using Controller.OnException() is a matter of preference for handling a specific subset of errors.
If I am just logging exception details in my web app, do I really need to put in exception handling logic for each tier? Why not just let them all bubble up the stack trace to the global.asax and log them there?
I would suggest against using any exception handling logic in any layer of your application unless:
The exception is not a fatal one, meaning that there is some action you can take to recover, or
The application should continue functioning and the exception should be "ignored." An example: when checking out at an online retailer you are sent a receipt via email. If that fails - but the other order processing stuff succeeds - the user should not be shown an error page. Here, we want the workflow to continue even though there is an exception. Most exceptions do not fall into this category.
Of course, exceptions - whether they are fatal or not or should be "ignored" or not - need to be logged and developers notified. This is best handled through an event handler for the Application.Error event. Yes, this can be done in Global.asax, but I think it's cleaner to use an HTTP Module-based approach, either Health Monitoring or ELMAH.
I've written an article on this topic that I'd like to recommend to you - Exception Handling Advice for ASP.NET Web Applications. Here is the article in summary:
My advice for handling exceptions in an ASP.NET application can be boiled down to the following guidelines:
(a) Create and use a meaningful custom error page.
(b) In general, do not catch exceptions. Let them bubble up to the ASP.NET runtime. Some cases where catching an exception makes sense include:
When there is a plausible way to recover from the exception by performing some alternative logic,
When a peripheral part of the application's workflow throws and exception and that exception should not derail the entire application, and
When you need to include additional information with the exception by throwing a new exception that has the original exception as its inner exception.
(c) Log all exceptions to some persistent store and use email (or some other medium) to notify developers when an exception occurs in production. Consider using ELMAH or ASP.NET's built-in Health Monitoring system to facilitate this process.
Exceptions should bubble up to whatever layer can handle them in a meaningful way, being aware of the Single Responsibility principle. For instance, your data layer should not be invested in logging.
The Application.Error event is a good place for catch-all error handling: that is, unexpected and/or fatal errors that require no special treatment beyond logging/alerting and redirecting to an error page.
If your web app makes use of the Microsoft AJAX extensions and partial postbacks, you'll need to handle exceptions in at least two places:
Global.asax
Your ScriptManager's OnAsyncPostBackError handler
For further information on OnAsyncPostBackError, check out:
http://msforge.net/blogs/janko/archive/2008/02/13/handling-exceptions-in-asp-net-ajax.aspx
http://msdn.microsoft.com/en-us/library/system.web.ui.scriptmanager.onasyncpostbackerror.aspx
I say that on global try to catch the error that you miss on the logic steps of your program and redirect them on an "error page", or a "not found page".
All other errors not necessary show the error on the user, and not need to send it to an error page.
For example, in page with 2 or more, different modules, if the one throw an error, just hide it, and show the rest. Similar try to catch errors when they happens and handle them the best non visual way to the user if this is possible, log them and correct them later.
Now this error that happens only on one module, you can see it on your log and correct it, but until you do that, user see something on your page and not a full error page.
Usually what I do is do a try...catch in the code, but instead of logging on the catch what I do is pass it on with a message stating where the error came from, etc. Then I use Elmah to catch all of the errors and log them.
That way you only have to deal with the logging in one area and satisfy the Single Responsiblity Principle, but you have more information available for debugging purposes. It can also be helpful when you get that data error that only seems to occur with 1 out of 500 users.
My ASP.NET app has a web.config healthMonitoring section set up to email me when errors occur. Periodically I get errors that I would like to ignore, such as Invalid Viewstate or ScriptResource.axd errors. Is there any way to configure web.config to NOT email me when the exception message matches a certain search string or regex?
I believe this is similar to Ignore HealthMonitoring event by EventDetailCode.
You can create a custom event provider by inheriting from the System.Web.Management.WebEventProvider base provider class. This way you could handle the errors you want to by emailing them and ignoring any others. Checkout "How to Write a Custom Web Event Provider for ASP.NET 2.0" and "Creating Custom Event Providers" for more info.
are you raising the events yourself, or are they raised in the background. I would look at the EventCode for the event and see if you can use that to distinguish between this event type and another? If you are raising the event yourself, like in a catch statement, you can easily separate it out. But if you are using the global blanket for catching all errors, there is no way. The only way is to use the event code in eventMapping and then add rules to catch that event and send it to a provider.
I'm using JQuery to load controls dynamically in an ASP.NET development environment using JSON and WebServices. Within this solution I have a business logic layer which has a built in validation mechanism (i.e. validating properties and business rules similar to that of CSLA)
When requesting a new control to be loaded dynamically using JQuery and an ASP.NET WebService, I would like to validate the input from the current control against the business logic validation mechanism (i.e. server side validation) and notify the user if there was any problems.
I managed to achieve this, however, when validation fails in the web service I would like to throw a customer exception containing the validation field id's and associated error messages.
In JQuery, I test for this specific ExceptionType and would like to apply the error messages dynamically to the controls listed in the exception type properties. This is where my problem comes in. Even though I created a custom exception with custom properties the exception that is passed to JQuery in JSON format from the WebService is still a standard exception with none of the additional properties listed. I could simply create a JSON formatted string of values in the exception's message property but would ultimately prefer something a little more elegant. Does anyone know how you can override the serialized exception created by ASP.NET for situations such as this...
Thank you in advance...
G
I ran into something very similar a couple days ago - basically there's no way to make ASP.NET generate custom exceptions. This is by design, since returning a specific type of exceptions would
[...] expose implementation
details/bugs to the clients. We could
do something with special exception
type that we let pass through, but its
too late for this release [...]
You could always return different HTTP status codes, and have the browser handle them as custom exceptions - for example, a 500 error would mean one thing, a 401 something else, etc. I think the best solution is to make your method return a string with the exception stack - not elegant, but at least this way the client has all the exception details.
Dave Ward also has info on ASP.NET AJAX service errors.