Your official information source from the .NET Web Development and Tools group at Microsoft.
System.Diagnostics.Trace can be a useful tool for logging and debugging, and sometimes it would be handy to be able to call one of the tracing methods from a Razor view.
For example, when an MVC application runs in production, by default MVC catches most application exceptions for you and routes them to Views/Shared/Error.cshtml. That view doesn’t show error details for security reasons, so you end up with the not-very-helpful message “An error occurred while processing your request.”
Running locally you get detailed error info, or you can catch exceptions by running in debug mode, but what to do about errors that happen in production?
If you can re-create the error in production, you can temporarily tell the site to go ahead and display detailed error information by adding a customErrors element to your Web.config file in the system.web element:
Now instead of “An error occurred” you get an actual error message and a stack trace.
But another quick-and-dirty alternative that doesn’t require temporarily exposing error details to the public, is to add tracing statements to the view, for example:
Unfortunately, when you do this you don’t get any trace output, and if you step through the code in the debugger you’ll see it step right over the TraceError method call without executing it.
Trace statements require the TRACE compiler constant, but it’s on by default and you can verify that in the Build tab of the project properties window:
The problem is that this setting in the .csproj file only applies to .cs files. ASP.NET uses a different compile process for .cshtml files (or .aspx files in Web Forms), and the settings for that compile process are in the Web.config file. If you don’t explicitly specify the TRACE constant there, tracing method calls in .cshtml views are ignored.
You have at least two options for dealing with this situation if you want to add tracing in a view: define a TRACE constant for the .cshtml compiler, or use a static helper method.
Below is an example of what you have to add to the application Web.config file for a Visual Studio project that targets .NET 4.5, in order to define a TRACE constant for the .cshtml compiler:
With this in place the TraceError method call gets executed.
If you’re using a different Visual Studio or ASP.NET version, you can get the Version number you need by looking at your root Web.config file, copying out the codedom element from there, and adding the compilerOptions setting. The root Web.config file for .NET 4 or 4.5 is located in C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.config:
If you’d rather use a static trace helper, create a class like the following example:
Now you can use virtually the same code in your view without having to add a codeDom element to your Web.config:
There are many ways to get the trace output, and I’ve added some links for info about that at the end of this post.
Adding tracing to views might be an effective way to debug a problem in production, and I’ve used Error.cshtml to show an example of how to do that. If your goal is a more permanent method of logging unhandled errors, a better method is to use an exception filter. To do that you create a class that implements IExceptionFilter, such as the following example:
And then register the filter in App_Start/FilterConfig.cs:
If you deploy your application to a Windows Azure Web Site, the latest SDK makes it exceptionally easy to get trace output immediately in the Visual Studio Output window while the site is running. In two weeks the tutorial I’ve written about this will be published on WindowsAzure.com; until then, see the intro in the ScottGu blog post introducing Windows Azure SDK 2.0.
Some other links:
Thanks to Rick Anderson and Yishai Galatzer for help with the code for this blog post.
Pretty useful stuff.
I also like the new code snippet widgets in this blog post. Huge improvement over what used to be,
Tracing isn't an effective way of capturing errors in Prod, as having <Deployment Retail="True"> is recommended on Prod servers (msdn.microsoft.com/.../system.web.configuration.deploymentsection.retail.aspx), which disables Trace output. We use other logging frameworks, such as Elmah or Log4Net.
@Tracing not recommended for Prod - Thanks for the comment. I agree ELMAH is a great tool, but it doesn't apply to all scenarios in which tracing is useful; I haven't used Log4Net. <Deployment Retail="True"> is described but isn't actually recommended for all production servers in the MSDN article you link to. Hosting providers I have experience with haven't use it, and Windows Azure Web Sites don't use it. In fact, System.Diagnostics tracing is integrated into Windows Azure Web Sites and Visual Studio in a way that makes it very convenient to turn tracing output on and off and get streaming logs or log file downloads.
MSDN blogs doesn't seem to be that deep , can we get some blogs more advanced ?
Hi Tom, that's useful, but How I can Trace in ASPX Views.
@garfieldzf - The only difference for an .aspx view is in how you wrap the code in the view, using angle bracket percent. I just tried both methods in an .aspx view, and both work.
Usefull , thanks (y)
@Tom
In production , i have to delete my extra code or i can keep all of this without warring about performance?
thanks
@Ben - Performance is mainly affected by how many logs you're actually writing, and trace listeners give you an option to log only Error-level, or Error and Warning, or Error, Warning, and Information, etc. logs. If you set the logging level to Error in production you probably aren't going to be writing a high volume of logs normally, then when you need to debug a problem, you can temporarily set the logging level to a more inclusive setting. The Trace statements themselves are not likely to have a noticeable impact on performance in most scenarios, but you can test that without changing your code by doing performance testing with and without the TRACE compiler constant defined. Without the compiler constant, the Trace statements aren't executed.
@Ben - A followup on tracing in production -- In the post I link to Scott Guthrie's recent NDC 2013 presentation on best practices for cloud applications. In that presentation he recommends keeping logging on in production at Warning level or Information level so you have historical data you can use for monitoring and analyzing issues, and switching to Verbose when you need more info for troubleshooting. His example takes advantage of cheap Windows Azure storage for storing large volumes of data, but the point applies to any web app -- the trivial performance hit of logging is more than offset by the benefits of having information about what's going on with the app in production. Scott's demo app uses System.Diagnostics.Trace.