Introduction
The .NET Framework is big. Really big. The System.Web
assembly, which contains the guts of ASP.NET, is comprised of nearly 2,000 types, over 23,000 methods, and more than 12,500 properties. And that's not counting any of the functionality added to ASP.NET since version 2.0. ASP.NET AJAX, the ListView control, Dynamic Data, URL routing, and other features add hundreds of new types and thousands of new methods and properties.
Given the size and scope of the .NET Framework and ASP.NET even there are certain to be dark corners for even the most experienced developers. There are certain classes, methods, and properties in the .NET Framework that every ASP.NET developer is intimately familiar with: the Request.QueryString
collection; the Session
object; Page
object properties like IsValid
and IsPostBack
. Yet even in these familiar classes there are very useful and very helpful properties, methods, and features that are less widely known. Heck, I've been building ASP.NET applications and writing about ASP.NET functionality and features full time since 2001, and once or twice a month I still stumble across an unknown feature or a helpful property or method buried in some dark corner of the framework.
This article lists four helpful methods, properties, and features in the .NET Framework that, in my experience, are not widely known to ASP.NET developers. Read on to see my list!
Typically, ASP.NET developers design, implement, and test their web applications from their personal computer, visiting the website through localhost
. When the site is ready to be deployed it is moved to a different web server and the visitors are remote, reaching the website from a domain name like www.yoursite.com. Likewise, when developing the application it is not uncommon to have debugging enabled, which entails going to Web.config
and setting the <compilation>
element's debug
attribute to true
. However, this setting should always be set to false
in production, as Scott Guthrie notes in his blog entry Don't run production ASP.NET Applications with debug="true"
enabled.
Sometimes its helpful to know if the user visiting the website is coming from localhost
or if debugging is enabled. For example, you might want to display debugging- or development-related information at the top of each web page, such as the time it took to execute the page or detailed information about the currently logged-in user. However, this information should not be shown to end users; rather, it should only be displayed if the user is visiting locally or if debugging is enabled.
The good news is that it's quite easy to determine whether a visitor has arrived at the site locally, thanks to the Response
object's IsLocal
property. Response.IsLocal
returns True if the visitor is coming from localhost, False
otherwise. To determine whether debugging is enabled, use the HttpContext
object's IsDebuggingEnabled
property. The code snippet below shows how to display a Panel (pnlDiagnosticInfo
) only if the user is arriving from localhost
and debugging is enabled.
|
Note that to use the HttpContext
object's properties you need to first use HttpContext.Current
to get a reference to the HttpContext
object associated with this request.
2. The Panel Web Control's DefaultButton
Property
A <form>
in a web page can be submitted in a number of ways: a user can click a submit button; JavaScript can submit the form by calling its submit()
function; or a user may hit Enter in a textbox. It's that last technique - hitting Enter in a textbox to submit the form - that can cause problems for web pages that contain multiple submit buttons. For example, an ASP.NET web application might have a master page that includes a search TextBox and Button Web control on every page. When the search Button on the master page is clicked, a postback ensues, the Button control's Click
event handler runs, and the user is taken to a page that displays the results of their search query.
Now, imagine a content page that uses this master page and contains its own TextBox controls and a Button control titled "Insert." When the Insert Button is clicked, there is a postback and the Button's Click
event handler fires, at which point a new record is added to the database, say.
What happens when we visit this content page in a browser, type some text into the search TextBox, and hit Enter? Hitting Enter causes the browser to submit the <form>
, but what Button does the browser indicate as having been "clicked?" If the browser says that the Search Button was clicked, then that Button's Click
event handler will fire on postback, but if the browser indicates that the Insert Button is clicked then that Button's Click
event handler will fire. Typically, when hitting Enter in a TextBox the browser will report that the first submit button in the form has been clicked. The net result is that regardless of whether the focus was in the Search TextBox or in one of the TextBox controls in the content page, the same Button will report as being "clicked" when the user hits the Enter key. What we want is for the browser to report that the Search Button was "clicked" when the user hits Enter in the search TextBox, and for the browser to report that the Insert Button was "clicked" when the user hits Enter from one of the TextBoxes in the content page. (For a more in-depth discussion of this problem, see Two Common Pitfalls When Submitting a Web Form Using the Enter Key.)
This conundrum can be fixed by placing the search TextBox and Button inside a Panel Web control and setting the Panel's DefaultButton
property to the ID
of the search Button Web control. The master page's markup would look something like:
|
Setting the Panel's DefaultButton
property causes the Panel to render with additional JavaScript that is triggered whenever the user presses a key when focused within the Panel. The JavaScript function monitors these keystrokes, and when the Enter key is pressed the code submits the <form>
, reporting that the associated Button control was clicked.
For more information on this property, check out my blog entry, The DefaultButton
Property - News To Me!
3. Creating Fully Qualified URLs Using Request.Url.GetLeftPart(UriPartial.Authority)
The Request
object includes a number of properties for determining path information. For example, the Request object's PhysicalPath
property returns the physical path to the currently executing page (e.g., D:\Websites\DemoApp\Tutorial01\MyPage.aspx
) whereas the Url
property returns the fully qualified URL of the currently requested page (e.g., http://www.yourserver.com/Tutorial01/MyPage.aspx
). But what if you want to build a fully qualified URL from scratch?
This is a common challenge when writing code that sends an e-mail that includes a URL back to the website. For example, if your site supports user accounts you might want to send newly registered users an e-mail message welcoming them to the site. You might want to include a URL to the login page in this e-mail. If you know the fully qualified URL of the login page - such as http://www.yourserver.com/Login.aspx - you can hard-code it into the e-mail's body. But what if you haven't settled on a domain name yet? Or what if the software you are developing will be used by various clients, each who have their own domain names? In this case you need to generate a fully qualified URL programmatically. You know the file name of the login page (~/Login.aspx
), but you need to write code to generate the left-hand portion, http://www.yourserver.com/, or perhaps http://www.yourserver.com/MyApp/, if the application is rooted at a virtual directory.
Rick Strahl shows how this information can be pieced together from various variables in the ServerVariables
collection, but there's an even easier way using the Request
object's Url
property's GetLeftPart
method. In short, the GetLeftPart
method returns the specified portion of the URL. The UriPartial.Authority
enumeration value passed into this method instructs GetLeftPart
method to return the protocol (http://
or https://
) along with the domain name and port number (if present). For example, if the requested page's URL is http://www.yourserver.com:8080/Tutorial01/MyPage.aspx
, then calling Request.Url.GetLeftPart(UriPartial.Authority)
returns the string http://www.yourserver.com:8080
.
The following code snippet shows how to build up a fully qualified URL for the login page using Request.Url.GetLeftPart(UriPartial.Authority)
:
|
The call to Page.ResolveUrl("~/Login.aspx")
generates a rooted path to the login page, such as /Tutorial01/Login.aspx
. The net effect is that loginUrl is assigned the fully qualified path to the login page, http://www.yourserver.com:8080/Tutorial01/Login.aspx
.
4. Taking An ASP.NET Web Application Offline
When performing maintenance on a production website, pushing up new or modified code/web pages, or taking any other sort of action that may disrupt a user's experience, it is a good idea to take the application offline and replace it with a single web page that explains that the website is currently unavailable. IIS, Microsoft's production-grade web server, includes an option to redirect all incoming traffic to a specific URL. This includes requests for any sort of content - ASP.NET pages, static HTML pages, images, CSS files, JavaScript files... whatever.
ASP.NET provides its own mechanism for taking an application offline. In short, if you upload a file to your website named App_Offline.htm
the ASP.NET engine will automatically display the contents of the App_Offline.htm
for any request to an ASP.NET page. By merely uploading such a file you effectively take your site offline and can display a nice-looking, informative message to visitors explaining why the site is offline, when you expect it to be back up, and so on. To bring the site back up, simply delete (or rename) the App_Offline.htm
file.
The main benefit of App_Offline.htm
over configuring IIS to redirect all traffic to a specified URL is that App_Offline.htm
can be used in virtually any environment, whereas configuring IIS requires access and permission to modify the web server's settings. Typically, such access is not granted in a shared hosting environment, making the App_Offline.htm
approach more amenable for such situations.
An earlier article on 4Guys, Taking an ASP.NET Application Offline, shows how to configure IIS to redirect all requests to a static URL, examines alternative approaches to taking an ASP.NET application offline, and discusses App_Offline.htm
in more detail. It also includes a demo on how to programmatically create the App_Offline.htm
file from a web page, thereby allowing a site to be taken offline from the web. (No need to FTP a file!)
Bear in mind that there are some subtleties that you must be aware of when using App_Offline.htm
. As noted in Taking an ASP.NET Application Offline:
The ASP.NET runtime will not return an App_Offline.htm
file if it exceeds 1 MB in size. Furthermore, if your App_Offline.htm
file is too small (less than 512 bytes), Internet Explorer will display its "friendly 404 error page" rather than the content returned by App_Offline.htm
(assuming friendly HTTP error pages are enabled in IE, which they are, by default).
Conclusion
Due to its size and scope, the .NET Framework has a lot of pigeonholes where useful functionality is tucked away. Even when working with the .NET Framework on a daily basis for years on end there are still spots that remain unexplored. This article shared four helpful bits of knowledge on ASP.NET that you may not have known about before. Is there a golden nugget or two in the .NET Framework that you use on a regular basis, but have found that your fellow developers are usually unaware of?