Figure 24-15 Edit and Continue Lack of Support, or Edit and Refresh Visual Basic 6 was all about developing things quickly, and its most powerful feature was the Edit and Continue featur
Trang 1Error Notifications
During an interactive debugging session, Visual Studio now strives to assist you with informative Error
Notifications These notifications not only report on events such as unhandled exceptions, but also offer
context-sensitive troubleshooting tips and next steps for dealing with the situation Figure 24-15 shows
an unhandledNullReferenceExceptionalong with the good advice that we might try using the ‘‘new’’
keyword to create an object instance before using it Oops!
Figure 24-15
Edit and Continue (Lack of) Support, or Edit and Refresh
Visual Basic 6 was all about developing things quickly, and its most powerful feature was the Edit and
Continue feature, which gave you capability to change code during a debugging session without
restart-ing the session In break mode, you could modify code fix bugs and move on The 2.0 version of the CLR
has restored this feature for both C# and Visual Basic Although this has a large number of developers
cheering, unfortunately this feature is not available to ASP.NET developers
In ASP.NET, your assembly is compiled not by Visual Studio, but by the ASP.NET runtime using the
same technique it does during a normal Web page request by a browser To cooperate with the debugger
and support Edit and Continue within ASP.NET, a number of fantastically complex modifications to
ASP.NET runtime would have been required by the development team Rather than including support
for this feature, ASP.NET developers can use page recycling.
This means that code changes are made during a debugging session, and then the whole page is refreshed
via F5, automatically recompiled, and re-executed Basically, ASP.NET 2.0 includes much improved
support for Edit and Refresh, but not for Edit and Continue
Just My Code Debugging
A new concept in the NET 2.0 CLR is called Just My Code debugging Any method in code can be
explicit-ly marked with the new attribute[DebuggerNonUserCode] Using this explicit technique and a number of
Trang 2other heuristic methods internal to the CLR, the debugger silently skips over code that isn’t important to the code at hand You can find the new preference Enable Just My Code in Tools ➪ Options ➪ Debugging The[DebuggerHidden]attribute is still available in NET 2.0 and hides methods from the debugger,
regardless of the user’s Just My Code preference The 1.1 attribute[DebuggerStepThrough]tells the
debugger to step through, rather than into, any method to which it’s applied; the[DebuggerNonUser
Code]attribute is a much more pervasive and complete implementation that works at runtime on dele-gates, virtual functions, and any arbitrarily complex code
Be aware that these attributes and this new user option exist to help you debug code effectively and
not be fooled by any confusing call stacks While these can be very useful, be sure not to use them on
your components until you’re sure you won’t accidentally hide the very error you’re trying to debug
Typically these attributes are used for components such as proxies or thin shim layers
Tracepoints
Breakpoints by themselves are useful for stopping execution either conditionally or unconditionally
Standard breakpoints break always Conditional breakpoints cause you to enter an interactive
debug-ging session based on a condition Tracing is useful to output the value of a variable or assertion to the debugger or to another location If you combine all these features, what do you get? Tracepoints, a new and powerful Visual Studio feature Tracepoints can save you from hitting breakpoints dozens of times just to catch an edge case variable value They can save you from covering your code with breakpoints to catch a strange case
To insert a Tracepoint, right-click in the code editor and select Breakpoint ➪ Insert Tracepoint You’ll get the dialog shown in Figure 24-16 The icon that indicates a breakpoint is a red circle, and the icon for a
Tracepoint is a red diamond Arbitrary strings can be created from the dialog using pseudo-variables
in the form of keywords such as$CALLSTACKor$FUNCTION, as well as the values of variables in scope
placed in curly braces In Figure 24-16, the value ofi.FirstName(placed in curly braces) is shown in the complete string with the Debug output of Visual Studio
Client-side Javascript Debugging
Excellent client-side Javascript Debugging is new in Visual Studio 2008 If you run an ASP.NET
appli-cation in a debugging session in Internet Explorer you’ll need to enable script debugging If not, you’ll
receive a dialog similar to the one in Figure 24-17
After you’ve turned on Script Debugging, try a simple ASPX page with some Javascript that changes the text in a textbox to UPPERCASE when the button is pressed
Listing 24-5: Simple Javascript debugging test
ASPX
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<script type="text/javascript">
function MakeItUpper()
Continued
Trang 3newText = document.getElementById("TextBox1").value.toUpperCase();
document.getElementById("TextBox1").value = newText;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<input type="button" id="Button1" value="Upper"
onclick="javascript:MakeItUpper()" />
<input type="text" id="TextBox1" runat="server"/>
</div>
</form>
</body>
</html>
Figure 24-16
Put a breakpoint on one of the lines of client-side Javascript Note that this is code that runs in the browser,
not on the Web server Start a debugging session with the page from Listing 24-5 Visual Studio will break
at that point, as shown in Figure 24-18
The Javascript debugger in Visual Studio 2008 supports variable tooltips, visualizers, call stacks, locals,
watches, and all the features you’re used to when debugging NET-based languages
Trang 4Figure 24-17
Figure 24-18
Trang 5Notice in the figure thatDefault.aspxhas the word [dynamic] listed on the tab, indicating that this isn’t
the samedefault.aspxthat was edited earlier; you can see thatdefault.aspxlisted on the final tab
Rather, this is the dynamically generateddefault.aspxthat was delivered to the browser, including
ViewState and other generated elements Dynamically generated documents and scripts appear during
the debug session in the Solution Explorer
This rich debugging support on the client side makes creating today’s Javascript-heavy AJAX
applica-tions much easier
SQL Stored Proc Debugging
Database projects are file-based projects that let you manage and execute database queries You can add
your existing SQL scripts to the project or create new ones and edit them within Visual Studio Database
projects and SQL debugging are not available in the Express or Standard versions of Visual Studio They
are available only in the Professional or Team Edition Visual Studio SKUs/versions
When debugging database applications, you can’t use Step Into (F11) to step between code in the
appli-cation tier into the code in SQL Server 2005 (be it T-SQL or CLR SQL) However, you can set a breakpoint
in the stored procedure code and use Continue (F5) to execute code to that set break point
When debugging SQL on SQL Server 2005, be aware of any software or hardware firewalls you may be
running Windows XP SP2’s software firewall will warn you what you’re trying to do Be sure to select
‘‘unblock’’ in any warning dialogs to ensure that SQL Server 2005 and Visual Studio can communicate
If you are using a SQL account to connect to the SQL Server, make sure the Windows User Account
you run Visual Studio under is also an administrator on the SQL Server machine You can add accounts
to SQL Server’ssysadminprivilege using the SQL commandsp_addsrvrolemember ’Domain\Name’,
’sysadmin’ Of course, never do this in production; and better yet, do your debugging on a machine
with everything installed locally
If you’re using the NT Authentication model on the SQL Server 2005, make sure that account has
per-missions to run thesp_enable_sql_debugstored procedure You can give account access to this stored
procedure by using the SQL commandsCREATE USER UserName FOR LOGIN ’Domain\Name’followed by
GRANT EXECUTE ON sp_enable_sql_debug TO UserName This creates a SQL user that is associated directly
with a specific Windows User and then explicitly grants permissions to debug TSQL to that user On SQL
Server 2000, the user must have access to the extended stored proceduresp_sdidebug
For slightly older installations such as Windows 2000 and Windows NT 4, or if you are using SQL 2000,
be sure to visit MSDN for the latest details and tools in this space The MSDN URL for debugging SQL
Server ishttp://msdn2.microsoft.com/library/zefbf0t6
Exception and Error Handling
When an exception occurs in your ASP.NET application code, you can handle it in a number of ways, but
the best approach is a multi-pronged one:
❑ Use aTry/Catcharound error-prone code This can always catch specific exceptions that
you can deal with, such asSystem.IO.FileNotFoundException
Trang 6❑ Rather than catching exceptions around specific chunks of code at the page level, consider using the page-level error handler to catch specific exceptions that might happen anywhere
on the page
❑ But prepare for unhandled exceptions:
❑ Set thePage.Errorproperty if a specific page should show a specific error page for any
unhandled exception This can also be done using the<%@ Page >directive or the code behind the property
❑ Have default error pages for 400 and 500 errors set in yourweb.config
❑ Have a boilerplateApplication_OnErrorhandler that takes into consideration both
spe-cific exceptions that you can do something about, as well as all unhandled exceptions that you may want logged to either the event log, a text file, or other instrumentation mechanism
The phrase unhandled exception may be alarming, but remember that you don’t do anyone any good
catching an exception that you can’t recover from Unhandled exceptions are okay if they are just that — exceptional For these situations, rely on global exception handlers for logging and friendly error pages that you can present to the user
Why try to catch an exception by adding code everywhere if you can catch and log
exceptions all in one place? A common mistake is creating a try/catch block around
some arbitrary code and catching the least specific exception type — System.
Exception A rule of thumb is, don’t catch any exception that you can’t do anything
about Just because an exception can be thrown by a particular method doesn’t
mean you have to catch it It’s exceptional, remember? Also, there are exception
handlers at both the page and the application level Catch exceptions in these two
centralized locations rather than all over.
Handling Exceptions on a Page
To handle exceptions at a page level, override theOnErrormethod thatSystem.Web.UI.Pageinherits
from theTemplateControlclass (see Listing 24-5) CallingServer.GetLastErrorgives you access to the exception that just occurred Be aware that a chain of exceptions may have occurred, and you can use the
ExceptionGetBaseExceptionmethod to return the root exception
Listing 24-6: Page-level error handling
VB
Protected Overrides Sub OnError(ByVal e As System.EventArgs)
Dim AnError As System.Exception = Server.GetLastError()
If (TypeOf AnError.GetBaseException() Is SomeSpecificException) Then
Response.Write("Something bad happened!") Response.StatusCode = 200
Server.ClearError() Response.End() End If
End Sub
Continued
Trang 7protected override void OnError(EventArgs e)
{
System.Exception anError = Server.GetLastError();
if (anError.GetBaseException() is SomeSpecificException)
{
Response.Write("Something bad happened!");
Response.StatusCode = 200;
Server.ClearError();
Response.End();
}
}
Handling Application Exceptions
The technique of catching exceptions in a centralized location can be applied to error handling at the
application level inGlobal.asax, as shown in Listing 24-6 If an exception is not caught on the page,
theweb.configis checked for an alternate error page; if there isn’t one, the exception bubbles up to the
application and your user sees a complete call stack
Listing 24-7: Application-level error handling
VB
Protected Sub Application_Error(sender as Object, ByVal e As System.EventArgs)
Dim bigError As System.Exception = Server.GetLastError()
’Example checking for HttpRequestValidationException
If (TypeOf bigError.GetBaseException() Is HttpRequestValidationException) Then
System.Diagnostics.Trace.WriteLine(bigError.ToString) Server.ClearError()
End If
End Sub
C#
protected void Application_Error(Object sender, EventArgs e)
{
System.Exception bigError = Server.GetLastError();
//Example checking for HttpRequestValidationException
if(bigError.GetBaseException() is HttpRequestValidationException )
{
System.Diagnostics.Trace.WriteLine(bigError.ToString());
Server.ClearError();
}
}
Unhandled application errors turn into HTTP Status Code 500 and display errors in the browser These
errors, including the complete callstack and other technical details, may be useful during development,
but are hardly useful at production time Most often, you want to create an error handler (as shown
previously) to log your error and to give the user a friendlier page to view
Trang 8If you ever find yourself trying to catch exceptions of type System.Exception , take a
look at the code to see whether you can avoid it There’s almost never a reason to
catch such a non-specific exception, and you’re more likely to swallow exceptions
that can provide valuable debugging Check the API documentation for the
framework method you are calling — a section specifically lists what exceptions an
API call might throw Never rely on an exception occurring to get a standard code
path to work.
Http Status Codes
EveryHttpRequestresults in anHttpResponse, and everyHttpResponseincludes a status code The
following table describes 11 particularly interesting HTTP status codes
Status Code Explanation
301 Moved
Permanently
Reminds the caller to use a new, permanent URL rather than the one he used to get here
302 Found Returned during a Response.Redirect This is the way to say ‘‘No, no, look over
here right now.’’
304 Not
Modified
Returned as the result of a conditionalGETwhen a requested document hasn’t been modified It is the basis of all browser-based caching An HTTP
message-body must not be returned when using a 304
307
Temporary
Redirect
Redirects calls to ASMX Web services to alternate URLs Rarely used with ASP.NET
400 Bad
Request
Request was malformed
401
Unauthorized
Request requires authentication from the user
403 Forbidden Authentication has failed, indicating that the server understood the requests but
cannot fulfill it
404 Not Found The server has not found an appropriate file or handler to handle this request
The implication is that this may be a temporary state This happens in ASP.NET not only because a file cannot be found, but also because it may be
inappropriately mapped to an IHttpHandler that was not available to service the request
410 Gone The equivalent of a permanent 404 indicating to the client that it should delete
any references to this link if possible 404s usually indicate that the server does not know whether the condition is permanent
Trang 9Status Code Explanation
500 Internal
Server Error
The official text for this error is ‘‘The server encountered an unexpected condition which prevented it from fulfilling the request,’’ but this error can occur when any unhandled exception bubbles all the way up to the user from
ASP.NET
Any status code greater than or equal to 400 is considered an error and, unless you configure otherwise,
the user will likely see an unfriendly message in his browser If you have not already handled these
errors inside of the ASP.NET runtime by checking their exception types, or if the error occurred outside
of ASP.NET and you want to show the user a friendly message, you can assign pages to any status code
withinweb.config, as the following example shows:
<customErrors mode ="On" >
<error statusCode ="500" redirect ="FriendlyMassiveError.aspx" />
</customErrors>
After making a change to the customer errors section of yourweb.config, make sure a page is available
to be shown to the user A classic mistake in error redirection is redirecting the user to a page that will
cause an error, thereby getting him stuck in a loop Use a great deal of care if you have complicated
headers or footers in your application that might cause an error if they appear on an error page Avoid
hitting the database or performing any other backend operation that requires either user authorization or
that the user’s session be in any specific state In other words, make sure that the error page is a reliable
standalone
Any status code greater than or equal to 400 increments the ASP.NET Requests
Failed performance counter 401 increments Requests Failed and Requests Not
Authorized 404 and 414 increment both Requests Failed and Requests Not Found.
Requests that result in a 500 status code increment Requests Failed and Requests
Timed Out If you’re going to return status codes, you must realize their effects and
their implications.
Summar y
This chapter examined the debugging tools available to you for creating robust ASP.NET applications
A successful debugging experience includes not only interactive debugging with new features such as
datatips, data visualizers, and error notifications, but also powerful options around configurable tracing
and logging of information
Remote debugging is easier than ever with ASP.NET, and the capability to write and debug ASP.NET
pages without installing IIS removes yet another layer of complexity from the development process
Visual Studio and its extensible debugging mechanisms continue to be expanded by intrepid bloggers
and enthusiasts, making debugging even less tedious than it has been in the past
Trang 10F ile I/O and Streams
Although most of this book concentrates specifically on learning and using the features of ASP.NET
3.5, NET provides an enormous amount of additional functionality in other areas of the Base Class
Library (BCL) This chapter examines a few of the common base classes that you can use to enhance
your ASP.NET applications First, you look at using the frameworksSystem.IOnamespace to
man-age files on the local file system Next, you explore how to use the various Stream classes within
the framework to read from and write different data formats to memory and the local file system
Finally, you learn how to use the NET Framework to communicate with other computers across
the Internet using common protocols such as HTTP and FTP
A Word about I/O Security
Although this chapter is not specifically about ASP.NET security, you need to
understand the impact of local system security on what the ASP.NET Worker Process
is allowed to do inside of the IO namespace Remember that generally, when your code
is executed by IIS, it executes under the context of the ASP.NET Worker Process user
account (ASPNET) and, therefore, your application may be restricted by that account’s
security rights For example, by default, the ASP.NET Worker Process does not have
rights to write to the local disk The two main areas that you should look at to get a
very basic understanding of the impact of security on an application are impersonation
and user account ACLs ASP.NET security is discussed thoroughly in Chapter 18
Additionally, this chapter demonstrates how to use classes in the BCL to delete files
and directories and to modify the permissions of directories and files Recognize that
it is entirely possible to permanently delete important data from your hard drive or
change the permissions of a resource, which would result in you losing the ability to
access the resource Be very careful when using these classes against the file system.