How to implement automatic bug/crash report for ASP.NET web application? - asp.net

Everyone probably notices that most modern applications nowadays has a way for user to send crash/bug report either automatically or with user permission. Some examples are Mozilla Crash Reporter or most Microsoft applications.
I really like this feature since it allows me to collect the bugs report quickly with helpful information than just let my user reports the bug/issue traditionally such as submit a help ticket.
I wonder if there is an easy or systematic way to implement that capability in ASP.NET web application.
Have you guys had any experience or knowledge to share for both WebForms and MVC applications? Or if this could be implemented in Client-side like JavaScript/JQuery, that'd be good.
Thanks!

ASP.NET 2.0 introducted Health monitoring, which allows you to do this by just adding some stuff to the web.config. See: http://msdn.microsoft.com/en-us/library/ms998306.aspx
It can log to mail, sql, eventlog, etc. and allows you to set buffers. So it for example won't kill your mailserver if the sql database goes down or if some user discovers a bug and tries to call it too often a second :-)
You can also log failed authentication and app pool restarts with it, it's pretty usefull if you just need it working quick. It's still questionnable if it is the best solution to manage all the errors. Because it might not got all the information you need, for example browser version or smt like that.

ELMAH is a library that plugs in and detects exceptions. You can also log an event yourself. The events and a great deal of data like url parameters and browser information can be emailed to administrators and optionally stored in a database for display. (Rather like an event log for the web site.) It doesn't have a built-in user form that I've seen, but can probably be extended to include such an option.
I've been using/customizing it for about two years now and it is really exceptional.
Another option might be to use Kampyle which includes a feedback box on the bottom right of your web site. You could use Javascript to trigger the box to appear if an issue is detected on the web site.

For an ASP.NET applicatino--or any Web application for that matter--isn't this just a two-step process of:
Logging the error (obviously); and
Put a form on the error document to allow the user to enter feedback.
Or is there more to this?

Your errors will pass through the Application_Error method of the Global.asax.cs file (which you may have to create). I use this fact to capture the error and log it to a database:
void Application_Error(object sender, EventArgs e)
{
try
{
SqlConnection errConnection = new SqlConnection("Your connection string");
// After setting up a command object, I call a stored procedure to save information about
// the crash. I pass two primary arguments. The first is the URL:
errCommand.Parameters.Add("#URL", SqlDbType.VarChar).Value = Request.Url.ToString();
// The second is the error information.
errCommand.Parameters.Add("#EI", SqlDbType.Text).Value = Server.GetLastError().ToString();
// I pass some other information from my session as well...
// After setting up an output parameter called ErrorID, I call the command...
errCommand.ExecuteNonQuery();
// Now Error ID is stored in the session.
Session["ErrorID"] = (int)ErrorID.Value;
}
catch { } // I do NOT want the error handling call to throw an error.
}
Now, you should have set up your Web.Config file so that a specific page gains control when an error occurs. In this page, you'll check the session for the error ID and show it to the user. In the output, I ask the user to write down the error if they would like to call us for more information. If we do receive a request, I can go into the database and get a complete trace of the error.

You can checkout my tutorial on how to implement exception logging in asp.net - http://jesal.us/blog/index.php/2008/04/08/exception-logging-using-the-database/

Related

Generic Exception Handler Orchestration in BizTalk

Hi All BizTalk Developers,
I need some input and guidance on how to design an Orchestration that can take few parameters as Input and log them in SQL server table (tblTrackingData)
I want to start this orchestration at various points, for example when I am calling a webservice so I want to log the request in DB and when I get the response then I want to log the response xml also in the same table.
In case of any exception I want to log error message and other details in the same table for tracking purpose.
Can some one guide me, direct me to some existing blogs/posts on how to handle this generic tracking / exceptions etc by starting a new Orchestration.
The purpose of a new Orchestration is to call it from anywhere, please suggest if it could be handled in a better way also.
Thanks.
The best advice, don't do this.
The reason? Everything you describe is already done by BizTalk Server automatically by BizTalk Tracking and the Event Log.
I can tell you from experience, you will not need anything else beyond Tracking and the Event Log.
I do recommend you implement proper exception handling within you app and log custom events, but they would also be written to a Windows Event Log only as well.

Windows Phone 7 - controls content and async request

I think this is trivial, but I cannot find the answer :(
I have a WP7 page that hosts some controls that I want to populate with date read from a web request.
The web request is done with:
WebClient wr = new WebClient();
wr.DownloadStringCompleted += new DownloadStringCompletedEventHandler(Event_DownloadStringCompleted);
wr.DownloadStringAsync(new Uri(theURL));
and this is called in the Page_Loaded event.
In Event_DownloadStringCompleted I try to assign the new values to the TextBlocks, that completely ignore this command.
What am I doing wrong? Do I need to find a different event to launch the web request? Or is it possible to "refresh" the page after the web request is completed?
Thanks
Your Event_DownloadStringCompleted is not called on the UI thread so it can't update the UI. Use the Dispatcher to get called back on the right thread. e.g.
page.Dispatcher.BeginInvoke(delegate() { textBlock.Text = "done!"; });
You might want to initiate the web request when the page's OnNavigatedTo() method is called, rather than when the page's Loaded event is fired, though I don't think this will solve your problem.
Are you sure that your handler of the DownloadStringCompleted event is called? If so, is the Error property of the DownloadStringCompletedEventArgs set to a non null value?
There are known display/refresh issues related to some display drivers introduced in the public beta. This has been known in some cases to be associated with ATI adapters. Some people report success following a driver update.
This may be affecting your refresh result.
Also you can check your driver is directx10 minimum and WDDM1.1 compliant per the WPDT system requirements. If not, driver upgrade (again), adapter change, or upgrade to Win7 if running Vista which has solved several obscure issues.
Also if you have the option, try running up your up on another PC with a different configuration.

Calling a method in an ASP.NET application from a Windows application

Other than using a web service, is there anyway to call a method in a web app from a windows application? Both run on the same machine.
I basically want to schedule a job to run a windows app which updates some file (for a bayesian spam filter), then I want to notify the web app to reload that file.
I know this can be done in other ways but I'm curious to know whether it's possible anyway.
You can make your windows app connect to the web app and do a GET in a page that responds by reloading your file, I don't think it is strictly necessary to use a web service. This way you can also make it happen from a web browser.
A Web Service is the "right" way if you want them to communicate directly. However, I've found it easier in some situations to coordinate via database records. For example, my web app has bulk email capability. To make it work, the web app just leaves a database record behind specifying the email to be sent. The WinApp scans periodically for these records and, when it finds one with an "unprocessed" status, it takes the appropriate action. This works like a charm for me in a very high volume environment.
You cannot quite do this in the other direction only because web apps don't generally sit around in a timing loop (there are ways around this but they aren't worth the effort). Thus, you'll require some type of initiating action to let the web app know when to reload the file. To do this, you could use the following code to do a GET on a page:
WebRequest wrContent = WebRequest.Create("http://www.yourUrl.com/yourpage.aspx");
Stream objStream = wrContent.GetResponse().GetResponseStream();
// I don't think you'll need the stream Reader but I include it for completeness
StreamReader objStreamReader = new StreamReader(objStream);
You'll then reload the file in the PageLoad method whenever this page is opened.
How is the web application loading the file? If you were using a dependency on the Cache object, then simply updating the file will invalidate the Cache entry, causing your code to reload that entry when it is found to be null (or based on the "invalidated" event).
Otherwise, I don't know how you would notify the application to update the file.
An ASP.NET application only exists as an instance to serve a request. This is why web services are an easy way to handle this - the application has been instantiated to serve the service request. If you could be sure the instance existed and got a handle to it, you could use remoting. But without having a concrete handle to an instance of the application, you can't invoke the method directly.
There's plenty of other ways to communicate. You could use a database or some other kind of list which both applications poll and update periodically. There are plenty of asynchronous MQ solutions out there.
So you'll create a page in your webapp specifically for this purpose. Use a Get request and pass in a url parameter. Then in the page_load event check for this paremter. if it exists then do your processing. By passing in the parameter you'll prevent accidental page loads that will cause the file to be uploaded and processed when you don't want it to be.
From the windows app make the url Get request by using the .Net HttpWebRequest. Example here: http://www.codeproject.com/KB/webservices/HttpWebRequest_Response.aspx

ASP.NET concurrency

I have an ASP.NET application that starts a long running operation during the Event Handler phase in the ASP.NET Page life cycle. This occurs when the end user pushes a button a bunch of queries are made to a database, a bunch of maps are generated, and then a movie is made from jpeg images of the maps. This process can take over a minute to complete.
Here's a link to the application
http://maxim.ucsd.edu/mapmaker/cbeo.aspx
I've tried using a thread from the threadpool, creating and launching my own thread and using AsyncCallback framework. The problem is that the new thread is run under a different userid. I assume the main thread is run under ASPNET, the new thread is run under AD\MAXIM$ where MAXIM is the hostname. I know this because there is an error when it tries to connect to the database.
Why is the new thread under a different userid?
If I can figure out the userid issue, what I'd like to do is check if the movie making process has finished by examining a Session variable in a Page_Load method, then add a link to the page to access the movie.
Does anyone have any good examples of using concurrency in a ASP.NET application that uses or creates threads in an EventHandler callback?
Thanks,
Matt
Did you read this?: http://msdn.microsoft.com/en-us/magazine/cc163725.aspx
Quoting one relevant portion from that link (you should read the whole thing):
A final point to keep in mind as you build asynchronous pages is that you should not launch asynchronous operations that borrow from the same thread pool that ASP.NET uses.
Not addressing the specific problem you asked about, but this is likely to come up soon:
At what point is this video used?
If it's displayed in the page or downloaded by the user, what does the generated html that the browser uses to get the video look like? The browser has to call that video somewhere using a separate http request, and you might do better by creating a separate http handler (*.ashx file) to handle that request, and just writing the url for that handler in your page.
If it's for storage or view elsewhere you should consider just saving the information needed to create the video at this point and deferring the actual work until the video is finally requested.
The problem is that the new thread is run under a different userid. I assume the main thread is run under ASPNET, the new thread is run under AD\MAXIM$ where MAXIM is the hostname.
ASPNET is a local account, when the request travels over a network it will use the computer's credentials (AD\MAXIM$).
What may be happening, is that you're running under impersonation in the request - and without in the ThreadPool. If that's the case, you might be able to store the current WindowsIdentity for the request, and then impersonate that identity in the ThreadPool.
Or, just let the ThreadPool hit the DB with Sql Authentication (username and password).

How do you log errors (Exceptions) in your ASP.NET apps?

I'm looking for the best way to log errors in an ASP.NET application.
I want to be able to receive emails when errors occurs in my application, with detailed information about the Exception and the current Request.
In my company we used to have our own ErrorMailer, catching everything in the Global.asax Application_Error. It was "Ok" but not very flexible nor configurable.
We switched recently to NLog. It's much more configurable, we can define different targets for the errors, filter them, buffer them (not tried yet). It's a very good improvement.
But I discovered lately that there's a whole Namespace in the .Net framework for this purpose : System.Web.Management and it can be configured in the healthMonitoring section of web.config.
Have you ever worked with .Net health monitoring? What is your solution for error logging?
I use elmah. It has some really nice features and here is a CodeProject article on it. I think the StackOverflow team uses elmah also!
I've been using Log4net, configured to email details of fatal errors. It's also set up to log everything to a log file, which is invaluable when trying to debug problems. The other benefit is that if that standard functionality doesn't do what you want it to, it's fairly easy to write a custom appender which can process the logging information as required.
Having said that, I'm using this in tandem with a custom error handler which sends out a html email with a bit more information than is included in the standard log4net emails - page, session variables, cookies, http server variables, etc.
These are both wired up in the Application_OnError event, where the exception is logged as a fatal exception in log4net (which then causes it to be emailed to a specified email address), and also handled using the custom error handler.
First heard about Elmah from the Coding Horror blog entry, Crash Responsibly, and although it looks promising I'm yet to implement it any projects.
I've been using the Enterprise Library's Logging objects. It allows you to have different types of logging (flat file, e-mail, and/or database). It's pretty customizable and has a pretty good interface for updating your web.config for the configuration of the logging. Usually I call my logging from the On Error in the Global.asax.
Here's a link to the MSDN
I use log4net and where ever I expect an exception I log it to the appropriate level. I tend not to re-throw the exception because it doesn't really allow for as-nice user experience, there is less info you can provide at the current state.
I'll have Application_Error also configured to catch any exception which was not expected and the error is logged as a Fatal priority through log4net (well, 404's are detected and logged as Info as they aren't that high severity).
My team uses log4net from Apache. It's pretty lightweight and easy to setup. Best of all, it's completely configurable from the web.config file, so once you've got the hooks in your code setup, you can completely change the way logging is done just by changing the web.config file.
log4net supports logging to a wide variety of locations - database, email, text file, Windows event log, etc. My team has it configured to send detailed error information to a database, and also send an email to the entire team with enough information for us to determine in which part of the code the error originated. Then we know who is responsible for that piece of code, and they can go to the database to get more detailed information.
I recently built an asp.net webservice with NLog, which I use for all my desktop apps. The logging works fine when I'm debugging in Visual Studio, but as soon as I switch to IIS the log file isn't created; I've not yet determined why, but it the fact that I need to look for a solution makes me want to try something else for my asp.net needs!
We use EnterpriseLibrary.ExceptionHandling.Logging. I like it a bit better than log4net because not only do we control the logging completely, but we can control the Throw/NoThrow decision within config as well.
We use a custom homegrown logging util we wrote. It requires you to implement logging on your own everywhere you need it. But, it also allows you to capture a lot more than just the exception.
For example our code would look like this:
Try
Dim p as New Person()
p.Name = "Joe"
p.Age = 30
Catch ex as Exception
Log.LogException(ex,"Err creating person and assigning name/age")
Throw ex
End Try
This way our logger will write all the info we need to a SQL database. We have email alerts set up at the DB level to look for certain errors or frequently occurring errors. It helps us identify exactly where the errors are coming from.
This might not be exactly what you're looking for. Another approach similar to using Global.asax is to us a code injection technique like AOP with PostSharp. This allows you to inject custom code at the beginning and end of every method or on every exception. It's an interesting approach but I believe it may have a heavy performance overhead.

Resources