Want to follow this site? Here's the RSS feed.

Exception Handlers for Silverlight 2.0

Tuesday, March 31, 2009

Whereas Themelia is my foundation for all .NET development, it’s a little known fact that I have an internal build of it specifically used for Silverlight.  Among the many features of Themelia for Silverlight (hereafter called “ThemeliaSL”) is something I call Exception Handlers.  This isn’t the same thing as the “catch” block of a try/catch.  No, it’s a concept specific to Silverlight.  Also, this is a fairly discrete feature that you can implement in your own Silverlight applications without the need of my full framework.  However, before you can understand this feature, you need to understand Silverlight currently works with unhandled exceptions.

When Silverlight throws an exception that’s unhandled, it eventually gets bubbled up to your System.Windows.Application instance.  If you are handling the UnhandledException event of this class, then you have an opportunity to handle this exception on your own.  When your UnhandledException event handler is called, you are passed an instance of System.Windows.ApplicationUnhandledExceptionEventArgs.  In this class you are provided a property named ExceptionObject of type System.Exception which holds the actual exception object that has been thrown.  There’s one other property though: Handled.  This property is a boolean which provides you with the ability to say whether you handled the exception or not.  If you set this property to true, then you are telling Silverlight that the problem has been taken care of.  If you set it to false, then you are telling Silverlight that it’s about to die.

That’s really all there is to Silverlight exception handling.  You can, however, make things a bit more streamlined.  Say, for example, you know of various types of exceptions that your application or underlying frameworks will throw.  You also know that you want to handle some of them in a specific way.  Or maybe, you just don’t want any communications exceptions to ever be sent back to the client.  For situations like these, you can use the concept I refer to as exception handlers.

Before we implement this concept, lets see how it will be used first:

public class Application : Themelia.Windows.Application
{
    public Application()
        : base()
    {
        AddExceptionHandler(typeof(CommunicationException), delegate(Exception ex)
        {
            if (ex.InnerException == null)
            {

                ReportExceptionToFirebug(ex.InnerException);
                return true;
            }
            //+ 
            return false;
        });
    }
}

Essentially, call the base constructor of the Application class we are about to create.  Then, for each exception that you want to handle, register it with the AddExceptionHandler method, sending it the type of the exception and a delegate of type Func<Exception, Boolean>.  In this example, when an unhandled exception of type CommunicationException is thrown, we automatically check to see if it has an inner exception.  If so, we report the exception in a special way and mark the exception as handled.

You could also add more exception handlers.  Here’s another example:

AddExceptionHandler(typeof(ArgumentException), delegate(Exception ex)
{
    ReportValidationError(ex);
    return true;
});

While this example is a rather silly one (because validation shouldn’t throw exceptions!), it does go to show you this is essentially a declarative model for exception handling.  Now it’s time to move on to build the thing.

First, create your own abstract version of System.Windows.Application.  This is typically a good idea anyways.  It allows you to control your applications in a very streamlined manner.  In this class, add the following static member:

private static Dictionary<Type, Func<Exception, Boolean>> HandlerRegistry = new Dictionary<Type, Func<Exception, Boolean>>();

This represents a registry of all exceptions handlers registered to your application.  It’s a dictionary with the key representing the Type of the exception and the value representing a delegate to be called when that exception is raised.

You’ll also need a standard .NET locking object:

private static Object _lock = new Object(); 

Now add the following method:

//- #AddExceptionHandler -// 
protected void AddExceptionHandler(Type type, Func<Exception, Boolean> handler)
{
    lock (_lock)
    {
        HandlerRegistry.Add(type, handler);
    }
}

This will allow you to register exception handlers from your concrete instance of your custom application class.

Now it’s on to the meat of the implementation.  In your base class application class constructor, handle the UnhandledException event.

this.UnhandledException += new EventHandler<System.Windows.ApplicationUnhandledExceptionEventArgs>(OnUnhandledException);

Then, in the method that will be called upon the event being raised, do something like this:

//- #OnUnhandledException -// 
protected virtual void OnUnhandledException(Object sender, ApplicationUnhandledExceptionEventArgs ea)
{
    lock (_lock)
    {
        if (HandlerRegistry.Count > 0)
        {
            Exception exception = ea.ExceptionObject;
            Type type = exception.GetType();
            if (HandlerRegistry.ContainsKey(type))
            {
                ea.Handled = HandlerRegistry[type](exception);
            }
        }
    }
    if (!System.Diagnostics.Debugger.IsAttached && this.AutoReportErrorToDOM && !ea.Handled)
    {
        ea.Handled = true;
        Deployment.Current.Dispatcher.BeginInvoke(delegate { ReportErrorToDOM(ea); });
    }
} 

Essentially, if there are any registered handlers, check to see if the currently thrown exception is one of those exception registered to be handled.  If so, then pull the delegate from the registry and call it.

Notice that the delegate that we registered is Func<Exception, Boolean>.  Functionally, this means is that the delegate will accept an Exception object and return a boolean.  Interpreted, this means that in the delegate you register you need to return a boolean representing whether you want the exception handled or not.

You may also notice in the above code that there is a property named AutoReportErrorToDOM.  This does exactly what it says  and it’s nothing too exciting:

//- @AutoReportErrorToDOM -// 
public Boolean AutoReportErrorToDOM { get; set; }

The ReportErrorToDOM method is the same one that Visual Studio 2008 throws in with the Silverlight template.  For completeness, here it is:

//- #ReportErrorToDOM -// 
protected void ReportErrorToDOM(ApplicationUnhandledExceptionEventArgs ea)
{
    try
    {
        String errorMsg = ea.ExceptionObject.Message + ea.ExceptionObject.StackTrace;
        errorMsg = errorMsg.Replace('"', '\'').Replace("\r\n", @"\n");
        System.Windows.Browser.HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight 2 Application " + errorMsg + "\");");
    }
    catch (Exception)
    {
    }
}

At this point, you have everything you need to make the samples that we went through work properly.  Just be sure to base your application class on the new one and you’ll be set.

One important note is that when you are using custom visual entities in Silverlight, you need to make sure that you properly register the namespace in XAML.  For example, say the above class was called “Application” in the “Themelia.Windows” CLR namespace in the “Themelia.Silverlight” assembly.  For this configuration, you would use the following xaml:

<t:Application 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:t="clr-namespace:Themelia.Windows;assembly=Themelia.Silverlight" 
    x:Class="Sample.Application" />

With this, you’re all set.

Tip: Quick Reflector Loading for .NET and Silverlight

Wednesday, March 18, 2009

In my daily development there are three tools that I keep open almost constantly:  Visual Studio 2008, Windows Debugger, and Reflector.  The first is obvious, the second is for extreme-debugging, and the third so I can have a clue what I’m working with (...I have NO idea how people do .NET or Silverlight development without reflector!)  The first two I access with icons, while the third is one that I open and close at least 10 times a day.

To quickly access reflector (as well as Notepad2 and a whole host of sysinternals apps!) I throw it in my Windows folder so I can access it from the Run box.  Not only that, but I typically rename tools I throw in there to have only one letter.  Reflector is “r”.  So, I hit Win-R and type “r”.  Up comes reflector.  Here’s the thing though: I work in both .NET and Silverlight equally.  Yet, Reflector only loads ONE of them.  What to do?

The fix is simple: copy r.exe to rs.exe.  When I load r.exe, I select .NET.  When I load rs.exe, I select Silverlight.  Now I when I hit Win-R, I can type either “r” or “rs” depending on what framework I want to inspect.  You could even take the concept further by making a “rf.exe” for the compact framework”  Each “x.exe” will have it’s own “x.cfg” so the configurations won’t bleed over each other.

Thanks for the feedback ! (Re: Understanding WCF Services in Silverlight 2)

Saturday, March 7, 2009

A few months back I published a document on my web site entitled "Understanding WCF Services in Silverlight 2".  I wrote this document so people could have a solid understand of how to use WCF as well as some of the core WCF best practices.  The document explains everything from data contracts to service contracts, from asynchronous communication to SSL security, and from fault management to JSON communication.  It did this for both .NET as well as Silverlight.

Well, goodness, it's definitely met my expectations.  It's quickly become the absolute top most traffic mover on my web site.  It even flew by my JavaScript Graphics Development publication, which was a traffic mover very hard to beat.  The document also ended up on the Microsoft WCF homepage for three months and... a Senior Program Manager of the Connected Systems division even asked me to speak at the Mix conference on the topic of the document (of course I turned him down... it's just so much easier NOT to speak at a conference.)

So, thanks to everyone to came to the web site to read the document online or to download the PDF or XPS version of it.  Thanks also to everyone who left positive feedback on the web site.  Apparently, the document really has helped a lot of people in their pursuit to understand WCF better.  As I expected (well, as I knew!), people are sick and tired of the same old boring drag-n-drop videos and template-based file creation nonsense which prohibits the actual learning of the technology.

Given the absolutely astounding lack of respect and gratitude I get in person, the comments from the web site have gone a long way in helping convince me that I should continue my research and publication of this type of material.  It's my hope that people continue to find benefit in my research and continue to take the time to drop me a line telling me it was helpful.

Themelia Framework B7 Released

Tuesday, March 3, 2009

Today I would like to announce the release of the latest release of Themelia: B7.  In the past the B stood for "Beta", now it's just "Build".  Also, keep in mind that I follow an extremely strict version of the dog food policy: I never release anything in a public beta until I'm using it on all my production web sites.

So, please, head to the Themelia Framework web site and download the new binaries.  If you have questions, drop me a line and I'll try to answer your questions, check out your bug report, or just take note of your feedback.  Also, if you are keeping track.... there was no public B6.  That was a private build.  B5 was the last public build.

This release of Themelia is a MAJOR release that has a TON of new additions.  Below is a somewhat brief list of the new features and changes.  Further documenation will be available on the Themelia web site in the future.  These changes and additions have been categorized into two sections: Core (for Themelia.dll, Themelia.Data.Common.dll, and Themelia.ServiceModel.dll) and Web (for Themelia.Web.dll).

Core Changes/Additions

  • Added Dynamic Emit Object Activation (for extremely fast type creation-- replaces Activator.CreateInstance)
  • Added new methods to Themelia.Template (to make text interpolation much easier - Themelia assembly).
  • The Themelia.Globalization namespace now contains the basis for Themelia's new Globalization model.  Using this model, you can now localize all your .NET assemblies without having to compile your resource files into your assemblies.
  • The quick-access peices of data for Themelia.Data.Common is now in it's own Themelia.Data.Common assembly.
  • Spanish resources of Themelia.Data.Common is now included with Themelia (in Themelia.Data.Common.es).  Using Themelia's localization model, these will automatically be used when using Themelia.Data.Common and the user's culture is "es".
  • Added TraceOutputSender and DebugOutputSender reporting senders to allow you to send tracing results to the windows OutputDebugString output (viewable via tools like DbgView).
  • Added Themelia.ArrayModifier to make shifting and striping of arrays easier.

Web Changes/Additions

  • Added Application Processors, a new type of processor which allows you to register logic for application start and end as well as session start and end-- replaces global.asax.
  • Added a premilinary config viewer option for the web. By enabling this in web.config and then you can view your themelia web configuration in a browser; a future release will probably have a much more rich viewer-- just no incentive to build that at this time.
  • Themelia.Web.HttpHandling (abstract) has properties for the various ASP.NET intrinsics and it had an Output property of type StringBuilder which gets written to the output stream when there is data in it.
  • Added Themelia.Web.HttpModule (abstract) to slightly simplify module creation.
  • Added Themelia.Web.PageLoader to make loading an ASPX page from an HttpHandler easier.
  • Added ParameterMap to Themelia.Web.Processing.ComponentBase to allow components quick access to parameters.
  • Added linked parameters to processor init parameters and components.  This allows you to register values in appSettings or connectionStrings and access them in your init parameters and components by something like "{AppSettings mySetting}" or "{ConnectionString myConnectionString}".  This allows you to keep values centralized.
  • Changed Themelia.Web.Routing to Themelia.Web.Processing.
  • Fall-through processors are now catch-all processors.  The interfaces have not changed other than that.
  • The HttpHandler base classes have been moved from Themelia.Web.Routing to Themelia.Web.
  • Default pages may now be used as a catch all using the useDefaultPageAsCatchAll web domain settings.  When set to true, this setting will send all non-registered traffic to your default page.  In previous builds, adding a catch-all redirect was already very simple: just add the RedirectFallThroughProcessor and set a redirect from all to "/".  Now, however you can do the same thing by setting useDefaultPageAsCatchAll to true.  This seemingly small addition is actually very powerful and has allowed me to remove big chunks of code from web components.
  • Configuration setting allowWebDomainMissingTrailingSlash is now enableWebDomainMissingSlash, allowMissingTrailingSlash is now enableMissingSlash, and allowDirectPageAccess is now enableDirectPageAccess.
  • Themelia.Web.Globalization.Translator will translate any text your throw at it into just about any language of your choice through the Google Translate API.
  • Themelia.Web.Globalization.PageTranslator allows you to quickly translate all text controls on an ASP.NET page into just about any language of your choice.  It can also detect the user's local culture and automatically translate the page into his or her own language.

For more detailed information on some of these, you may consult the documentation on the Themelia web site.  For very specific information, contact me and I'll help you out.

You can download Themelia from http://www.themeliapro.com/.

(0 Comments)

Creative Commons License
This work is licensed under a Creative Commons Attribution 2.5 License.

Built on Themelia Pro 2.0

Mini-icons are part of the Silk Icons set of icons at famfamfam.com