When applications display ASP.NET runtime error messages to the end user, the root cause of the problem is due to insufficient error handling within the application. To gain the most granular control over errors, ASP.NET page events should be wrapped in a try…catch block so that proper error handling can be performed. However, the runtime does not provide this by default, so it must be manually performed. Any time something must be done manually the potential exists for a human to forget. Fortunately there are other features provided by ASP.NET that can provide a higher level of control.

Note – While it is also possible to implement a custom IHttpModule to perform error handling, it is out of scope for this post.

The ASP.NET framework essentially adds three additional ways to perform error handling by using, page events, application events and custom error handling in the app.config file. The first of these three, page events, allows the developer to use the Page_Error event handler to process any unhandled exceptions by subscribing to the the Error event inherited from the System.Web.UI.TemplateControl class. This can be done on each page to allow for fine grained control over the error handling. However, as with any event, you must be sure to manually subscribe, or use the AutoEventWireup feature. Developers that use this method must also consider whether or not the error should be bubbled up to the application level. In order to prevent the propagation from happening the handler must make a call to Server.ClearError() once the exception is properly handled. Applications that use a custom base class for all pages can use this feature to catch all unhandled exceptions. However, since inheritance sometimes must be broken, ASP.NET provides a simpler way to do this.

The second error handling method provided by the ASP.NET framework, application events, performs nearly the same functionality as the page event handler. The difference is that the Application_Error will catch any unhandled exceptions within an application’s scope. This handler must subscribe to the System.Web.HttpApplication’s Error event in the application’s global.asax file. Note that the AutoEventWireup and the Server.ClearError() concerns from the Page_Error description above also apply to the Application_Error event handler. However, once the error is handled at the application level, it might be advisable to let the user know something happened so they can notify someone. If the Server.ClearError() method is not called then another feature of ASP.NET can be put to use.

The last handling method provided by the ASP.NET framework is the <customErrors /> element in the web.config file. This element allows for an application to specify a default page to go to when there is an unhandled exception by using the defaultRedirect attribute. Simply set the value of the attribute to a relative or fully qualified hyperlink that the application should use. In order for the application to use this page the value of the mode attribute must also be set to “On” or “RemoteOnly”. Setting the value to “RemoteOnly” allows a system administrator to log on to the machine where the error is occurring and allow the ASP.NET runtime error message to display in the browser. For development environments this value is often set to “Off” so that the developers can see the error messages that are occurring. This is extremely helpful when an application writes messages to the event log, but the developers don’t have the necessary privileges to view the event log. The customError element also allows a developer to tailor how various HTTP status codes are handled by nesting an <error/> element inside.

Copyright © Scott P. Rudy 2009 All Rights Reserved
Advertisements

I am currently involved in a project that uses ASP.NET. The project is on its second implementation. During the first implementation the environment was controlled by the project team and they chose to turn on persistent sessions for the load balancers. This allowed the system to store session data in memory for the application.

Now the project is being rolled out for a new client where the environment is no longer controlled by the team. The client has specified that a central session server must be used so that the load balancers can be used without persistant sessions, as a recommended best practice by the vendor, F5 Networks.

I was tasked to assess the readiness of the product to be placed in this environment. After changing the web.config file to point to the new session server I immediately started seeing problems with pages not loading correctly. The problem was I couldn’t debug the issue because the .Net Framework was doing the work and I didn’t have source code or PDB files for the libraries. I guessed the issue dealt with serialization since objects that cannot be serialized will not go across the wire to the session server. So I took the first page the application hits and placed the following code into the Page_Load event handler (wrapped by a try…catch, of course):

IFormatter formatter = new BinaryFormatter();
using (System.IO.Stream stream = new System.IO.FileStream(
    "C:\\Users\\rudyscot\\desktop\\userstate.bin",
    System.IO.FileMode.Create, System.IO.FileAccess.Write,
    System.IO.FileShare.None))
{
    formatter.Serialize(stream, Session);
    stream.Flush();
    stream.Close();
}

Any issues with the serialization will throw an exception, so I was able to see what the issues were by looking at the Message property of the caught Exception. All of the issues turned out to be what I was expecting. They were all classes not marked with a Serialization attribute. Unfortunately, one of the objects turned out to be a .Net framework object though, so code changes needed to occur to move the needed properties of that control to an object that could be serialized.

Copyright © Scott P. Rudy 2009 All Rights Reserved

I haven’t been really keen on using the AJAX features within .NET to date. I had been using the XMLHTTP feature in IE for years and just didn’t see the need. However, the other day I had a need to collapse some data within a ListView and I really didn’t want to figure out how to render the script properly to do this (read: I wanted to do something easy). The ListView is control that is deserving of its own post as it gives complete control over how HTML is rendered, a big change from some of the other data controls that have shipped earlier in .Net. There are plenty of examples on how to use the ListView control on the web. However, when it came to the CollapsiblePanelExtender control, I had a bit of trouble finding any good examples. After spending about an hour with the CollapsiblePanel I feel there are some basic usage rules missing on the control’s website. The properties of the control are well documented, but I really needed to know how to wire the control up. Essentially I wanted this:

Show:

[-] My Items

Here is the data I want to hide and show.

Hide:

[+] My Items

It turns out the simple way to get it setup is to use a Panel for the data you want to hide, AND a panel to host the label that you want to control the show and hide functionality. In addition, you need a style to change the cursor when the user hovers over your label. So it would look something like this:

<style type="text/css">
    .ExpanderLabel {cursor:pointer;}
</style>
<cc1:CollapsiblePanelExtender ID="MyPanelExtender"
    runat="server" TargetControlID="MyItemsPanel"
    CollapsedText="[+] My Items"
    ExpandedText="[-] My Items"
    TextLabelID="MyItemsPanelLabel"
    ExpandControlID="MyItemsPanelControl"
    CollapseControlID="MyItemsPanelControl"
    SuppressPostBack="true"/>
<asp:Panel ID="MyItemsPanelControl" runat="server">
    <asp:Label Width="100%"
        CssClass="MyItemsPanelLabel"
        ToolTip="Click to Show/Hide this section"
        ID="MyItemsPanelLabel" runat="server" />
</asp:Panel>
<asp:Panel ID="MyItemsPanel" runat="server">
    Here is the data I want to hide and show.
</asp:Panel>

 

So the CollapsablePanelExtender references a TargetControlID which contains the actual data I want to hide. It also references the ExpandControlID and the CollapseControlID which I wanted to be the same. The last set of references is to the TextLabelID, CollapsedText and ExpandedText. This set controls the text that will be shown as a title bar for the data section.

Copyright © Scott P. Rudy 2009 All Rights Reserved