"Power ASP.NET 2.0 Programming"Jeff ProsiseBoston .NET User Group
September 15, 2004

Jeff Prosise of Wintellect was on hand (courtesy of INETA) to deliver the night's main session. He wanted to “give us a break" from what he called the usual ASP.NET 2.0 talks, so he focused on topics that have not been given much limelight to date in the Whidbey world. (Thanks to Chris Pels for use of the photo!)
ASP.NET Client Callback Manager
This feature in ASP.NET allows pages to perform lightweight callbacks to the server. The approach avoids having to fully process and refresh the page, therefore there is no page flashing and, more importantly, much less load on the server/network. It does this by using Microsoft's XMLHTTP ActiveX control under the covers to make a call to the server, which returns a simple string which can be parsed on the client with JavaScript.
To do this, you create a JavaScript client-side function which will be called when the server has completed the callback. The approach Jeff showed was embedding this script as a string in the codebehind and registering this on the page with RegisterClientScriptBlock(). You wire up the page to make the callback to the server by calling GetCallbackEventReference() and adding this to a specific control using .Attributes.Add("onclick",...).
The page which receives the callback must implement ICallbackEventHandler. This simple interface requires implementation of the RaiseCallbackEvent() method. This receives the callback from the browser, accepting a string which the client can use to communicate what it needs. The method returns a string that can be parsed by the previously registered client-side JavaScript function.
This approach is very useful to update client information when it is changed on the server. Jeff showed a simple example page which displayed details of three stocks. The page was configured to callback to the server every few seconds. Remember, this action requires very little overhead, unlike using the Meta-Refresh approach commonly used today. The page was driven from a simple XML file. When he made a change to the XML file, updating a stock price, almost immediately after he saved the file, the rendered page displayed the updated price.
Unfortunately, because the callback manager functionality relies on XMLHTTP, this (generally) limits clients to Internet Explorer only.
For more information, there is an article on the Callback Manager here:
http://www.ondotnet.com/lpt/a/5035
Configuration API
This new API in ASP.NET 2.0 allows easy management of configuration settings. It merges all settings up the configuration "chain" (e.g. machine.config, web.config, etc.)
A powerful feature of this API is support for encryption. You can encrypt and decrypt almost all sections of your configuration files, including any user-defined sections. There are some exceptions, such as the section, which needs to be accessed outside of ASP.NET by some IIS ISAPI code and therefore cannot be encrypted.
Encryption is performed through the ProtectSection()/UnProtectSection() methods, which can be configured to use either RSA or 3DES. They key is stored in the operating system (via DPAPI) in the Local Security Authority (LSA). While this avoids the catch-22 of putting it inside a configuration file, it requires running separate installation functions on each server to get the key into the LSA. This means you cannot simply rely on XCopy deployment for initial server launch.
ASP.NET 2.0 supports a new configuration section called . As the name suggests, it allows for simple and, via encryption through the Configuration API, secure storage of database connection strings. It is important to note that this is not under the section. Having them separate adds another layer of safety.
There is currently no visual tool in Visual Studio for these features, you must rely on programming against the API. Jeff hoped out loud that the VS team might have time to include one in the Beta 2 timeframe.
Here is a QuickStart sample on these features.
Health Monitoring Subsystem
With the new Health Monitoring subsystem, you can configure ASP.NET to send notifications of errors as they occur. These notifications can contain exception details, stack trace, browser information, request headers and more.
You specify settings under the new section of web.config and machine.config. You can define application events and friendly names with <eventMappings>, create notification targets with , and use to map an event to one or more of those providers (e.g. email, Windows event log, a file, database, WMI, etc.) For example, you can easily have all unhandled exceptions sent to a debugging email address.
You can also configure filters which indicate maximum frequencies for notifications. In other words, only send one email for this error every 10 minutes. This is quite useful to prevent flooding of email boxes or database servers should an error result from a commonly-accessed page.
In addition, the subsystem can be configured to send out periodic "heartbeats" of status details, which allows external monitoring to ensure that a target application is running as expected.
You can easily define custom events to plug into the subsystem. Your class must derive from WebBaseEvent (or WebBaseErrorEvent) and override FormatCustomEventDetails() to return a string representing as much or as little detail as you'd like. The basic properties are message, source and eventID, but it is easy to add your own.
It's clear the ASP.NET 2.0 team took notice of supplemental logging and exception management frameworks such as the Exception Management Application Block and the Enterprise Instrumentation Framework. At Monster, we've long relied on the Exception Block for just these purposes (sending email, logging to database, etc.), so it's great to see native support for these actions will be coming. I wonder how Microsoft will guide developers in choosing between these features and those of the Microsoft's/Avanade's Enterprise Library's Exception Block.
Ben Lovell has a post on Health Montioring with an example project:
http://bitarray.co.uk/ben/articles/245.aspx
UPDATE: Fellow Boston .NET UG member Girish Bharadwaj was inspired by Jeff's talk and wrote a very good post on the health monitoring subsystem.
"$" Expressions and Expression Builders
Jeff demonstrated a new syntax usable from ASP.NET pages to load values from resource files, configuration files and even custom sources. For example:
" Runat="server">
This accesses the section of web.config and returns the value found at the "SomeKey" node. You could use syntax like to return the database connection string as configured in the (new) section of web.config. Similar functionality can be used from the codebehind as well.
You can create your own custom expression builders by deriving from System.Web.Compilation.ExpressionBuilder and overriding the CodeBLOCKED EXPRESSION method. You register them in the section of web.config. You can then reference your custom builder with the same syntax as above (e.g. ).
Fredrik Normen has a great post on this:
http://normen.mine.nu/viewpost.aspx?PostID=161
Here is Jeff's own post on the subject:
http://wintellect.com/WEBLOGS/wintellect/archive/2004/07/22/295.aspx
Multiple Logical Forms and Validation Groups
Supporting the concept of multiple logical forms has always been a challenge in ASP.NET. You might have two submit buttons, each logically associated with different sets of fields, but clicking either would invoke all of the validators on the page, not generally what was intended.
With 2.0, all controls support the concept of "validation groups" via a ValidationGroup property. You assign the same name to all of the controls, including validators, in your logical form. When you submit your page, only the validators associated with the current group are executed.
On the server side, you can still use Page.IsValid() as this reflects only the state of the validators group selected with the last postback. In addition, you can check a specific group using Page.IsValid("TheGroupName").
A simple example can be found at Johan Normen's blog:
http://www.nsquared2.net/johan/viewpost.aspx?PostID=51
Default Actions
Another source of difficulty prior to 2.0 has been assigning default buttons and actions to fields which receive an "enter" keypress. A large number of custom workarounds exist, but with 2.0, a simple native solution exists.
You can now add a Panel control to your form and set the DefaultButton property to point to the control you wish to receive a click when enter is pressed in one of the Panel's controls. The Form supports the DefaultButton property as well.
If you're looking for a solution for your current applications, look at the Default Button workspace on GotDotNet.
Image Generation Service
Jeff discussed features in ASP.NET surrounding generation of images and how retrieving images from a data store and displaying on a page is very straightforward.
Unfortunately, this functionality is to be gutted with the Beta 2 release. Jeff showed a simple workaround where the IMG tag's src property points to a custom HttpHandler (e.g. "http://example.com/imageGenerator.ashx?width=100&height=50&Text=Hello")
An example of creating this HttpHandler can be found here:
http://weblogs.asp.net/ShankuN/archive/2004/08/16/215487.aspx
Conclusion
It was a great night. Jeff is a fantastic speaker and I'm sure everyone learned at least one Nugget of Usefulness. Many thanks to INETA for footing the bill and to Jeff for making the time for us.
-Chris
I've been trying to use my (free) Brinkster account to host images for my blog, but they seem to discourage direct linking from any pages not on your Brinkster site, so I searched for (free) alternatives.
Luckily, image hosting is also a large concern for the many people who use online auction services. I found a very good resource for picture hosting, each with summaries and rankings at Auction Orbit:
http://www.auctionorbit.com/freeimagehosting.htm
The one I went with is http://photobucket.com. They allow direct linking, up to 2500 MB/month bandwidth and 100 MB of storage. Did I mention the price was... zero? Very hard to argue with that. They'll even remove the bandwidth and storage space restrictions and give you access to FTP upload if you support them with a donation (as little as $5.)
Another interesting one was http://www.imageshack.us. You don't even need to create an account. Just upload an image and they'll display a link you can use to reference that picture. It will stay active until one year has passed without any hits. You can also create a free account, which will allow you to manage your pictures, view statistics, upload multiple pictures with a .ZIP file, etc.
Walagata (http://walagata.com/) also offers free image hosting, but only allocates a set number of free accounts per month. It looks like the window is currently closed for free accounts, but there will probably be more in a few weeks.
-Chris
I'm sure everyone is reading Fritz Onion's blog, but for the handful who do not, Fritz has a great post about creating custom build providers in ASP.NET 2.0.
The main point is that the “/code” (soon to be changed to “/Application_Code“) directory under your ASP.NET 2.0 web site can host files with custom extensions (in addition to the out-of-the-box supported .cs, .vb, .wsdl and .xsd.) You write a build provider and associate the file's extension with it, then ASP.NET will automatically invoke your provider. You supply the CodeDom logic in the build provider and ASP.NET will make the resulting assembly automatically available to your web site's code (with full IntelliSense.)
We've been doing something similar for quite some time here at Monster by leveraging the CodeDom for certain aspects of our data access, so it seems this could be a great feature for us to leverage.
I'm continually impressed with the number of things that have gotten better with Whidbey. Now, I'm off to find some more.
-Chris
As luck would have it, I happened to be at Microsoft in Redmond this week while the local user group, Dot Net Users, was hosting Avanade's Tim Shakarian. Tim gave a very interesting talk about the upcoming Enterprise Library and dove into detail on the Exception Handling Application Block. Tom Hollander (PM on the Microsoft PAG team) was also present to help answer questions.
Here is a summary of my notes from the session:
Enterprise Library
Enterprise Library (EntLib) is a redevelopment of the Application Blocks currently hosted by the Patterns & Practices team at Microsoft. The blocks are “reusable software components designed to assist developers with common enterprise development challenges.” The EntLib is not currently available to the public, as they are now available only to Avanade, Microsoft and select partners (via the Enterprise Library Partner Program.) They are setting expectations that the EntLib will be available no sooner than January. During the intervening months, Avanade is rebuilding their Avanade Connected Architecture for .NET (ACA.NET) framework upon the services of the EntLib. (Note that the two are distinct efforts - EntLib are the free/community-based/open utilities, ACA.NET is a proprietary, more fully-featured framework which Avanade will use on client projects.)
When released, they will be part of the Microsoft Patterns & Practices library, free for use and will include all of the associated unit tests (current count is 1,900+) and documentation/samples in C# and VB.NET.
There is quite a bit of documentation available at GotDotNet. As Tim happily pointed out, the workspace is so popular that you can just go to the main GotDotNet Workspaces directory page and see it there. But here is the link.
The blocks include:
- Caching - It's for, uh, caching
- Security - Authentication, authorization, basic profile management, etc.
- Data Access - SQL Server, DB2 and Oracle will be supported out of the box
- Crypto - Easy-to-use but extensible encryption
- Exception Handling - (Described in detail below)
- Logging - Used individually or by other blocks to log messages to configured targets
- Configuration - Leveraged by the other blocks (see below)
They are all fully extensible, featuring pluggable providers, replaceable block implementations and guidelines on writing new blocks.
They are designed to work together (e.g. the Exception Handling leverages Logging, Security leverages Crypto, etc.), but they can be used individually.
Tim demonstrated the use of a windows-based Enterprise Library Configuration Console, which drives all EntLib settings for an app and modifies the appropriate .config file for the application to work with the proper EntLib settings. The Console can be extended to add your own custom creations.
Two additional versions are in the pipeline for EntLib. Version 2 will include more blocks for AOP and SOA, more community participation and an expanded Partner Program. Version 3 (release to coincide with Whidbey) will ensure the EntLib is compliant will all of the new platform's recommended practices.
Exception Handling Application Block
After the overview of the EntLib, Tim spent the remainder of the session giving an overview of the Exception Handling Application Block.
Here's an example invocation:
if (ExceptionPolicy.HandleException(ex, "MyPolicy"))
throw;
That's it. The power and flexibility lie in the configuration settings.
Basically, you define one or more Exception Policies. A Policy contains one or more Exception Types (e.g. “System.ArgumentException“.) And each Type contains one or more Exception Handlers.
Exception Handlers tell the system what to do when an Exception of the designated Type is received by the Policy. There will be three Handlers shipped with V1:
- LoggingExceptionHandler
- Uses Logging Application Block, but others could be plugged in (e.g. Log4Net)
- Defaults to event log.
- WrapHandler
- Wraps the original exception with a new Exception type, as specified in configuration
- The original Exception will remain available through the InnerExeption property
- ReplaceExceptionHandler
- Drops the original Exception and places a new Exception in its place (as configured)
Handlers always execute in a configured order. Each Handler has the opportunity to take some action upon the Exception (e.g. wrapping it) and the current exception is then passed along to the next Handler in the chain.
Once the configured Handlers have executed, there is a post-handling action which you can specify as one of the following:
- RethrowAction.None - No rethrow should occur
- RethrowAction.Notify - Tells the calling application that the Policy recommends the Exception should be rethrown.
- RethrowAction.Throw - Throws the resulting Exception to the calling application after all Handlers in the chain have executed. (Again, this may or may not be the original Exception.)
This explains why the (simple) code example above is based on an expression, not a fire-and-forget metaphor used with the current Exception Management Application Block.
The Block ships with two Formatters for logging or displaying Exception details: TextExceptionFormatter and XmlExceptionFormatter. The formatters use Reflection to iterate over any members of the Exception and create and output either in Text or XML. This is very similar to what the current Exception Management Application Block does. Note that the use of Reflection helps to automatically log any custom properties of your own Exception types.
You can easily create custom Handlers. Your class simply implements the very small IExceptionHandler interface. If you wish to have your Handler read settings from the configuration, it should also implement the IConfigurationProvider interface. Tim showed an example of this and it seemed very straightforward.
Being an active user of several of the current Application Blocks, I enthusiastically look forward to working with this new suite next year. Many thanks to Tim for a great presentation. I hope Tim will consider giving a similar talk to the Boston .NET User Group should he be in the area in the coming months!
-Chris