Friday, October 23, 2009

Using the ResolveUrl method inside your class library Business Logic Layer (BLL)

Getting around passing HttpContext.Current to your business logic layer, or BLL.


The Problem: 
You want to use handy methods like ResolveUrl inside your Business Logic Layer (BLL) which is a class library. You don't want to reference System.Web or any .Net framework library beneath the System.Web subsystem inside your BLL libraries.

The Fix:
Create a small Utility class inside your class library and pass it a delegate. I know, I'm not a big fan of Utility (or similar) classes but sometimes you need a little tool-belt class for miscellaneous utilitarian methods. I actually have a Common class library that has even less dependencies than my typical BLL library which is where I stuck this class. Obviously, place the code where appropriate for your solution.



using System; 
namespace Common 
{ 
    public static class Utility 
    { 
        public static Func<string, string> ResolveUrl; 
    } 
} 

Now in your global.asax place the following.

private void Session_Start(object sender, EventArgs e) 
{ 
    AssignBusinessLogicLayerHelpers(); 
} 

private static void AssignBusinessLogicLayerHelpers() 
{ 
    var context = HttpContext.Current; 
    if (context == null) return; 

    var page = context.Handler as Page; if (page == null) return; 

    // assign the resolve url method 
    if (Utility.ResolveUrl == null) 
    { 
        Utility.ResolveUrl = page.ResolveUrl; 
    } 

    // assign other helper methods here... 
} 


Here we've elegantly passed a generic delegate to our Utility class that will reference back to the provided ResolveUrl method. The method stamp deals with primitive types only (strings) so we have no dependencies passing this function pointer across the domains.

The Why:  

You do not want to have a BLL or similar class library system utilizing System.Web, or System.Windows.Forms for that matter. If you have a solution with a web service, a web site and a common class library (BLL or other) and you start using methods dependent on HttpContext.Current you are going to run into issues as this context is not the same between the web service and your web site. A common scenario might be a LINQ2SQL Business Object Layer on top of your SQL Database which has effectively become your BLL. You may have classes that need to store virtual, resolved paths into the database but you want to place the resolving of the URL inside your business object classes to enforce a  strong encapsulation of the class. Here's an easy, 5 minute way to provide such features to your business objects without breaking your nTier application model. Now you can happily store the AvatarUrl of your users in the database and have your aspnet_User class do the resolution on the fly!

No comments: