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

Microsoft MVP (ASP.NET) 2009

Thursday, October 2, 2008

I'm rather pleased to announce that October 1, 2008 was my day: I was made a Microsoft MVP for ASP.NET.  Thus, as tradition seems to state, I'm posting a blog entry about it.

Thanks to God for not letting me have the MVP until now, the timing is flawless.  Thanks also to my MVP advisor David Silverlight who got me more serious about the MVP program and admitted to having nominated me.  Next, thanks to Scott Hanselman who fixed a clog in the MVP pipeline.  Apparently, I was in the system, but completely lost; in the wrong category or something.  He took it upon himself to contact a few people to get the problem fixed.

Thanks also to Brad Abrams for his recommendation to the MVP committee and to Rick Strahl, a fellow MVP, Microsoft ASP.NET AJAX loather, and Subversion lover who showed me that open source developers have equal rights to the MVP title.

To bring in the new [MVP] year, today I took some time and did a massive redesign to my web site featuring the cool MVP logo, which just so happens to fit perfectly in my existing color scheme.  I'll probably be tweaking the site over the next few days as the waves of whimsical changes come my way.

Themelia Foundation 2.0 Beta 3 Released

Tuesday, September 23, 2008

This weekend I was finally able to release beta 3 of my Themelia Foundation 2.0.  This foundation, primarily for the web, provides a new paradigm in web development through its advanced HTTP routing subsystem.  That's not all Themelia is or does, but it will probably be the primary aspect of it that people think of.  It's also not the type of HTTP routing you are used to with simple URL rewriting systems or .NET 3.5 SP1's built in routing system.  It's, in fact, a new type of web development.

In order to help people understand and use Themelia effectively, I have written (and rewritten) extensive documentation for various of its features.  There are still a few more documents to be posted, but all of the HTTP routing specific docs are already posted here on my NetFXHarmonics.com web site.  Below is a list, in order, of the various Themelia docs:

At beta 3, Themelia is feature complete.  There shouldn't be any more major interface changes.  Therefore, at this time I need people to start using it.  The excuse of "I can't use beta software" doesn't work in the real world as using beta software is how software goes gets out of beta.  Also, the exceedingly naive and unprofessional excuse of "I can't use open source" software doesn't work at all as the lines between open-source (e.g. Prototype/JQuery/Firefox/Chrome), shared-source (e.g. .NET Framework), and commercial software (e.g. Windows) blurs more by the day.  Adapt or be assimilated.

Of course, you can always look over the code of Themelia to increase your own awareness of various areas of technology.  Perhaps you want to learn more about dependency injection or want to see how to deal with HTTP handler mappings using IIS7's integrated runtime.  Whatever.  The code is up there for your reading pleasure.  Also, if you have some sort of optimization technique you would like to suggest or even an architectural recommendation, send it my way.

Fundamentals of Themelia - Redirects

Tuesday, September 9, 2008

This documentation has been updated for Themelia Framework 2.0 Beta 3.

Sometimes you want to handle a route with an HTTP handler, sometimes you want to do a rewrite, but other times you may want to just a simple redirect.  Maybe something moved, or you just want a "shrink" URL on your web site so others can find a link faster.  Fortunately, Themelia provides the ability to setup redirects in a variety of different ways.  In fact, they are basically the same ways you setup a rewrite.

The first way to setup a redirect is the two-part model of setting up a redirect handler and writing a redirect entry:

<themelia.web>
  <webDomains>
    <add>
      <handlers>
        <add matchType="pathStartsWith" name="Redirect" text="jd8" />
      </handlers>
      <redirects>
        <add match="jd8" destination="http://www.somedudeswebsite.com/this/is/a/really/long/url/no/one/will/remember" priority="5" />
      </redirects>
    </add>
  </webDomains>
</themelia.web>

This method should be nearly self explanatory: your handler routes all paths that start with "jd8" to the "Redirect" handler.  When the "Redirect" handler loads, it knows to look in it's area (<redirects>) for the appropriate information.  It looks for a match and, based on the highest priority (1 highest to 10 lowest), finds the best match against the current path.  The best redirect entry then had then directs the user to the URL in the destination attribute.  It's important to note that just like the url rewrite entries, redirect entries don't work off "match types" like "contains", "startsWith" or "endsWith", but it finds the first match going from highest (1) priority to lowest (10).  However, this isn't your only option for matching a redirect.

Initialization Parameters

The other option you have is to use Themelia initialization parameters.  Various features in Themelia support this and while the mechanics of them are beyond the scope of the current discussion, using them for redirects is very simple.  The basic idea is that instead of doing a two-part registration of a redirect, you tell the handler itself some information that will be passed to the handler.  As you will see form the following example, the initialization parameter syntax for redirects makes Themelia redirects even simpler to work with:

<themelia.web>
  <webDomains>
    <add>
      <handlers>
        <add matchType="pathStartsWith" name="Redirect" text="jd8">
          <parameters>
            <add name="Destination" value="http://www.somedudeswebsite.com/this/is/a/really/long/url/no/one/will/remember" />
          </parameters>
        </add>
      </handlers>
    </add>
  </webDomains>
</themelia.web>

All you need to do is set the destination parameter to the appropriate URL and you're done.

Redirect FallThrough Processor

Say you had an entire section of your web site that you would like to use for nothing but redirects.  Perhaps you would like to setup a /shrink/ path on your web site to allow easy to remember URLs for your company or family.  If you understand the fundamentals of Themelia, your mind should lean towards using a web domain with a fallthrough processor for redirects.  Well, guess what... Themelia ships with a fallthrough processor called the RedirectFallThroughProcessor.  This scenario is easily created by the following sample syntax:

<themelia.web>
  <webDomains>
    <add name="shrink" path="shrink">
      <fallThroughProcessors>
        <add type="RedirectFallThroughProcessor" />
      </fallThroughProcessors>
      <redirects>
        <add match="jd8" destination="http://www.somedudeswebsite.com/this/is/a/really/long/url/no/one/will/remember" priority="4" />
        <add match="f93" destination="http://www.somedudeswebsite.com/this/is/another/really/long/url/no/one/will/remember" priority="5" />
        <add match="d8l" destination="http://www.somedudeswebsite.com/this/is/yet/another/really/long/url/no/one/will/remember" priority="7" />
      </redirects>
    </add>
  </webDomains>
</themelia.web>

Now your people can simply go to http://www.yourwebsite.com/shrink/jd8, http://www.yourwebsite.com/shrink/jd8, and http://www.yourwebsite.com/shrink/jd8 to access the long URLs.

Custom Redirecting

If you are rather ambitious, perhaps you would like a more powerful mechanism for dynamically storing shrunk URLs.  Using Themelia this is also incredibly simple.  Though we could store out shrunk URLs anywhere, especially in a database, for our example, lets store them in a plain old XML file that looks like the following redirect.xml file:

<shrink>
  <url matchType="webDomainPathStartsWith" alias="the" target="http://www.codeplex.com/themelia/" />
  <url matchType="webDomainPathStartsWith" alias="dev" target="http://www.codeplex.com/devserver/" />
  <url matchType="webDomainPathStartsWith" alias="min" target="http://www.codeplex.com/minima/" />
</shrink>

Now what we can do is create a custom fallthrough processor which catches all requests in a web domain and matches them against our XML file (of course, in reality we would use a database with caching with properly set dependencies, but for the same of our example, XML without locking is easier to demonstrate):

using System;
//+
namespace Sample.Web.Routing
{
    public class CustomRedirectFallthroughProcessor : Themelia.Web.Routing.FallThroughProcessorBase
    {
        //- @GetHandler -//
        public override System.Web.IHttpHandler GetHandler(System.Web.HttpContext context, String requestType, String virtualPath, String path, params Object[] parameterArray)
        {
            System.IO.StreamReader reader = new System.IO.StreamReader(@"redirect.xml");
            System.Xml.XmlReader xmlReader = System.Xml.XmlReader.Create(reader);
            while (xmlReader.Read())
            {
                if (xmlReader.NodeType == System.Xml.XmlNodeType.Element)
                {
                    String matchType = xmlReader.GetAttribute("matchType");
                    String alias = xmlReader.GetAttribute("alias");
                    String target = xmlReader.GetAttribute("target");
                    //+
                    if (Themelia.Web.Routing.RouteMatcher.Match(matchType, alias))
                    {
                        Themelia.Web.Http.Redirect(target);
                    }
                }
            }
            //+
            return null;
        }
    }
}

Now all we have to do is register our fallthrough processor in our "shrink" web domain and viola, we have our own URL shrink server:

<themelia.web>
  <webDomains>
    <add name="shrink" path="shrink">
      <fallThroughProcessors>
        <add type="Sample.Web.Routing.CustomRedirectFallthroughProcessor, Sample.Web" />
      </fallThroughProcessors>
    </add>
  </webDomains>
</themelia.web>

With this example www.yourdomain.com/shrink/the goes to http://www.codeplex.com/themelia, www.yourdomain.com/shrink/dev goes to http://www.codeplex.com/devserver,  and www.yourdomain.com/shrink/min goes to http://www.codeplex.com/minima.  Given other matchTypes or different web domains, you can match different types of patterns as well.

That's really all there is to it.  No longer do you need to rely on an external service for all your URLs and no more importing and updating URLs.  If your data were in a centralized database, everything could be connected to that centralized location.  Not only that, but you would, of course, split this up into various web domains to allow each web domain to have its own shrunk URLs.

404 Replacement

This isn't always a good idea.  In fact, it's rarely a good idea.  However, for internal applications, it could be rather helpful.  Sometimes you don't want 404 messages on your application at all (on a web site, you normally want to leave them.) In these, situations perhaps you want a redirect to another location when an improper link is accessed.  The Themelia configuration for this is simple:

<themelia.web>
  <webDomains>
    <add>
      <fallThroughProcessors>
        <add type="RedirectFallThroughProcessor" />
      </fallThroughProcessors>
      <redirects>
        <add match="" destination="/" />
      </redirects>
    </add>
  </webDomains>
</themelia.web>

In short, we have the redirect fallthrough processor with a catch all redirect sending the user to the root.  This will effectively send all access to non-registered areas of your application to the root. Remember also that redirects like every other Themelia feature allows for priority, so you can put other catches in there as well.  Just set the blank one with a lower (higher number) priority than the others.

Links

Fundamentals of Themelia - Error Processors

Thursday, September 4, 2008

This documentation has been updated for Themelia Framework 2.0 Beta 3.

Regardless of what type of web site you are building, you absolutely must have some way to have the web site tell you that it's having problems.  If the web site isn't important enough to keep up, I can't see how it's important enough to put up in the first place.  Thus, ASP.NET developers tap into the beauty of the HttpApplication object's Error event.  By handling this event, we get immediate notification whenever an unhandled exception is thrown anywhere on the web site. For personal web sites, this is awesome, but corporate web sites, it could keep you from being fired. 

When I mention the Error event to junior developers (this is one of the things which, to me, defines a junior developer), they immediately think I'm talking about Global.asax.  Yes, it's related to Global.asax , but that's not where we're going to do this.  This isn't ASP.  This is ASP.NET.  Just because the letters of the file name contain "Global.asa", that doesn't mean it's the same thing  This is the powerful and professional beast known as ASP.NET and as such we should apply the best tried and true elegant design pattern and best practices wherever possible.  In this case, this means not putting all kinds of stuff into your Global.asax file.

Aside from the magical Application_Start method and its buddies, which must be in Global.asax, this file is really just a connection to the web site's HttpApplication instance.  Furthermore, since we are in an object-oriented world, we can inherit from that and keep our implementation away from the file entirely.  Thus the average Global.asax file should look like this:

<%@ Application Language="C#" Inherits="MySite.Web.HttpApplication" %>

That's it.  Well, unless you need the Application_Start method (or its buddies), but for the most part that's it.  Don't go handling events in there.  You will have your own HttpApplication class with error handling in another place. Here's an example:

namespace MySite.Web
{
    public class HttpApplication : System.Web.HttpApplication
    {
        //- @Init -//
        public override void Init()
        {
            this.Error += new EventHandler(OnError);
            //+
            base.Init();
        }

        //- $OnError -//
        private void OnError(Object sender, EventArgs e)
        {
            HttpApplication ha = sender as HttpApplication;
            if (ha != null)
            {
                System.Web.HttpContext context = ha.Context;
                Themelia.Tracing.ReportFacade.Send(context.Error);
            }
        }
    }
}

This example traps each unhandled exception and sends it to the default exception notification contact in Themelia.  All exception details including all inner exceptions will be included in the e-mail.

This is primarily the ASP.NET world before Themelia 2.0 (well, the ReportFacade is Themelia 2.0!): you trap an error and send it, save it, or whatever.

Themelia 2.0 Error Processors

In the real world, sometimes you don't need to be notified of every error on every part of your web site.  Sometimes you only need to know about a certain sensitive portion.  The rest, perhaps, can be saved into a database or queued up for sending once a day.  On the other hand, some parts of a web site should not just notify you of an exception, it should also be logged... in triplicate.  Thus Themelia 2.0 provides error processors which handle error within the boundaries of a web domain.

If you recall, a web domain is a Themelia 2.0 concept that bring the idea of an AppDomain to the web.  What happens in a web domain, stays in the web domain.  Thus, if you register an error processor in a web domain, you will only see error about that particular web domain.

Configuration of error processors is incredibly simply: just register one in a web domain.  Period!

Here's the actual configuration, which replaces everything we did with Global.asax and the custom HttpApplication file:

<themelia.web>
  <webDomains>
    <errorProcessors>
      <add type="EmailSendingErrorProcessor" />
    </errorProcessors>
  </webDomains>
</themelia.web>

In this sample, EmailSendingErrorProcessor is an error processor provided by Themelia and is, obviously, registered in Themelia's processor factory to allow it's usage outside of declaring it's full type (Themelia.Web.Routing.EmailSendingErrorProcessor, Themelia.Web).

If you would like to create your own custom error processor, just create a class which inherits from Themelia.Web.Routing.ErrorProcessorBase.  This abstract class requires that you implement one method:

void OnErrorProcessorExecute(System.Web.HttpContext context, params Object[] parameterArray)

In this method you can do whatever you want.  Here's a sample custom error processor:

namespace Sample.Web.Routing
{
    public class SavingErrorProcessor : Themelia.Web.Routing.ErrorProcessorBase
    {
        public override void OnErrorProcessorExecute(System.Web.HttpContext context, params Object[] parameterArray)
        {
            Exception ex = context.Error;
            if (ex != null && !Themelia.Web.Http.UrlPartArray.Contains("problem"))
            {
                String problemGuid = Web.ExceptionSaver.Save(ex);
                Themelia.Web.Http.Redirect("/problem/" + problemGuid);
            }
            else
            {
                try
                {
                    Themelia.Tracing.ReportFacade.Send("Unknown exception occurred");
                }
                catch
                {
                    //+ just in case the sample web.config isn't configured for mail
                }
            }
        }
    }
}

In this sample (as seen in the Themelia "Basic" sample), when an exception is thrown that is not caught by anyone, this error processor will catch it and check if we are already on the problem page.  If we aren't, then save the exception in the database and send the reference to the appropriate page to allow the user to enter in a description of what he or she was doing when the exception was raised.  If the exception was thrown on that page... oops, then just send us an alert so we know to get on it right away.

Error Processors in WebDomain Inheritance

In the following example, we have three web domains each with its own configuration:

<themelia.web>
  <webDomains>
    <add>
      <errorProcessors>
        <add type="Sample.Web.Routing.SavingErrorProcessor, Sample.Web" />
      </errorProcessors>
    </add>
    <add name="sales" path="sales">
      <errorProcessors>
        <add type="EmailSendingErrorProcessor" />
      </errorProcessors>
    </add>
    <add name="finance" path="finance" basedOn="sales">
      <errorProcessors>
        <add type="Sample.Web.Routing.DatabaseSavingErrorProcessor, Sample.Web" />
      </errorProcessors>
    </add>
  </webDomains>
</themelia.web>

When the root webdomain has an error, the exception is handled as we previously explained.  If the sales web domain has a problem, send an alert immediately.  Finally, notice that the finance web domain is based on the sales web domain.  Thus, when an error is raised in the finance web domain, an email is sent immediately and the error is saved to the database (assuming thats what the DatabaseSavingErrorProcessor does!) To be clear, this does NOT mean that sales errors will go to the finance web domain.  Web domain inheritance just copies configuration and maintains the protective boundaries.  Thus each web domain will see only its' own exceptions.

Thus, using Themelia 2.0 you have fine grained control over how your exceptions are handled in various parts of your web site.  Not only that, your error processors are always packages in nice little envelopes (called classes!) which can be easily reused on various other sites.

Links

Fundamentals of Themelia - Processor Factories

Tuesday, August 26, 2008

This documentation has been updated for Themelia Framework 2.0 Beta 3.

One of the most basics concepts in Themelia is the aliased handler factory.  If you recall, this allows simplified access to any HTTP handler.  In stead of registering a handler as "Sample.Web.AuthenticateHandler, Sample.Web", you could simply use "Authenticate" or "Auth" depending on how your aliased handler factory was setup.  This factory also created the HTTP handler thereby giving a small boost in performance over dynamically creating an instance of "Sample.Web.AuthenticateHandler, Sample.Web".

Analogous to this is a processor factory, it's identical every every way to an aliased handler factory, except that it generated any and all types of processors.  You can alias pre processors, mid processors, fall through processors, error processors, post processors, post state processors, and even injection processors.  Thus, instead of registering the long name of "Themelia.Web.Routing.ForbiddenFallThroughProcessor, Themelia.Web" you may simply register "ForbiddenFallThroughProcessor".

In fact, for our example, let's look at Themelia's internal processor factory:

internal class CommonProcessorFactory : Themelia.Web.Routing.ProcessorFactoryBase
{
    //- @CreateProcessor -//
    public override IProcessor CreateProcessor(String text)
    {
        switch (text)
        {
            case "passthrough":
                return new PassThroughPreProcessor();
            case "emailsendingerrorprocessor":
                return new EmailSendingErrorProcessor();
            case "forbiddenfallthroughprocessor":
                return new ForbiddenFallThroughProcessor();
            case "passthroughfallthroughprocessor":
                return new PassThroughFallThroughProcessor();
            case "webformfallthroughprocessor":
                return new WebFormFallThroughProcessor();
            case "urlrewritefallthroughprocessor":
                return new UrlRewriteFallThroughProcessor();
            case "redirectfallthroughprocessor":
                return new RedirectFallThroughProcessor();
        }
        //+
        return null;
    }
}

As you can see, every common reusable processor type is registered so that you don't need to write out the entire type each time.  Also, once again, we have a small performance boost since dynamic creation is now out of the question.  As a side note to this, where as handlers are created on each request (lest they share stale state), processors have no state and therefore can be reused.  Therefore, Themelia only actually creates once instance of each processor you register regardless if you are using a processor factory or not.  So, the performance boost in a processor factory isn't nearly that much as the boost in a aliased handler factory.  However, it sure does help you remember the name of the types.

It's important to remember that you can use a processor factory for any type of processor.  You also do not need to have a separate processor factory for each type of processor.

A processor factory is made by creating a class that inherits from Themelia.Web.Routing.ProcessorFactoryBase. This is an abstract class that requires you to implement the following signature:

IProcessor CreateProcessor(String text)

They may be registered in web.config like this:

<themelia.web>
  <webDomains>
    <add>
      <processorFactories>
        <add type="Sample.Web.Routing.ProcessorFactory, Sample.Web" />
      </processorFactories>
    </add>
  </webDomains>
</themelia.web>

Lastly, processor factories are also installed by web components, thus showing once again that web components are the end all for the Themelia pipeline.  You register one Themelia web component and all your Themelia functionality is registered and running.

Links

Math Problem: (type the answer in the box)

Notice: all comments are subject to moderation.

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

Powered by the Minima Blog Engine 3.1 and Squid Micro-Blogging Library.

Built on Themelia Framework 2.0

Developed using NetFXHarmonics DevServer 1.0.

(all of which are NetFXHarmonics products created by David Betz)

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