The Freak Parade

Strange noises from the mind of Nathan Stults…
  • rss
  • Home
  • About The Freak Parade

Rule Based Access Control using an Expression Evaluator

September 17, 2008

I’ve written previously about “claims based authorization,” and how I believe it will eventually become a ubiquitous approach to identity management as the world of online digital identity reinvents itself in order to avoid implosion. If you aren’t familiar with the concept of claims based identity, I recommend checking out the post linked above or following some of the links from this post.  If you just want to examine the sample code for this post, it is here.

In this post I’m interested in how a set of claims presented by a user when making a service call can be evaluated against specific authorization rules to determine whether or not the user has access to the requested resource.

The details of how a user is associated with such claims, how they are secured, and how claims are embedded inside calls to your service are beyond the scope of this post, but the links listed above should provide a place to put the tip of that chisel. For the purposes of this post I will assume that claims are presented via a list of IClaim objects, and an IClaim is nothing but a Name/Value pair - IList<IClaim>. This is very similar to how Micrisofts new Zermatt Identity Framework represents claims, and this was intentional as I believe that Zermatt is probably the future of Identity Management on the .NET platform.

So then, given IList<IClaim> claims, how can we make rational authorization decisions, such as “I only want users who are in the Premium Members role and whose age is older than 21 to access this (probably seedy) service method.” One obvious, simple approach would be to evaluate the claims programmatically. Some simple extension methods can make this much easier:


public static class ClaimsExtensions
{
   public static T GetClaimValue<t>(this IList<iclaim> claims, string claimType)
   {
       foreach (IClaim claim in claims)
       {
           if (String.Compare(claim.ClaimType, claimType, true) == 0)
           {
               return TypeNormalizer.EnsureType<t>(claim.Value, default(T));
           }
       }
       return default(T);
   }

   public static bool ClaimEqualsAny(this IList<iclaim> claims, string claimType, string claimValue)
   {
       foreach (IClaim claim in claims)
       {
           if (String.Compare(claim.ClaimType, claimType, true) == 0)
           {
               if (claim.Value.Equals(claimValue, StringComparison.InvariantCultureIgnoreCase))
                   return true;
           }
       }
       return false;
   }

   public static bool EvaluateClaim<t>(this IList<iclaim> claims, string claimType, Func<t , bool> eval)
   {
       var claimValue = claims.GetClaimValue</t><t>(claimType);
       return eval(claimValue);
   }
}

Then, from within a method that needs protecting, you can easily do something like this:


public void MyServiceMethod()
{
    if (CurrentUser.Claims.EvaluateClaim<int>(CustomClaimTypes.AgeInYears,age => age < 21) ||
        CurrentUser.Claims.ClaimEqualsAny(CustomClaimTypes.Role,"Premium User") == false)
    {
	//Whatever you do when someone isn't authorized. Throw a not authorized exception? Return a fault code?
    }

    //Implement your service method here, your user is old enough and has paid their money
}

If you were clever, you could probably figure out a way to use LINQ expressions to make the syntax even cleaner. This is all good and well, but it has at least one major problem - authorization rules are probably likely to change far more frequently than your application code. Even worse, you may wish your power users to be able to manage their own authorization rules for certain kinds of access or for named permissions. Using the technique described above, any change to any authorization rule will require you compile and deploy your application.

One common solution to conundrums such as these is to use a DSL (Domain Specific Language). And while you certainly could write a custom DSL to implement your authorization rules, authorization rules have an interesting characteristic: they always resolve to a discrete value, a true or a false. They are simply boolean expressions.

There are a number of Expression Evaluators available from the open source community that will fit the bill perfectly. An Expression Evaluator will allow you to specify your authorization rules as simple strings, which means they can be stored in a configuration file or a database or some other persistent store and modified and run-time as needed. They are also serializable by definition and can easily be requested by and cached at the user interface to allow the user interface to use the same authorization logic  to render itself appropriately with respect to the permissions of the currently logged in user that the server will use to authorize access to its API without (necessarily) having any code in common other than a reference to the same expression evaluator library.

In this example I will be using Simple Expression Evaluator available on Codeplex. I chose this library purely out of nepotism, because I wrote it, but you should be able to use any expression evaluator that catches your fancy. A number of options for .NET are listed here.

Using an Simple Expression Evaluator we could rewrite the above authorization rule like this:

AgeInYears >= 21 and MatchesAny(Role = "Premium User")

In the sample project I added a custom function, IsInRole, allowing this syntax:

AgeInYears >= 21 and IsInRole("Premium User")

To make this happen, Simple Expression Evaluator will need a little help in interpreting claim names. The main reason behind this is that claims are usually represented by a URI, such as http://thefreakparade.com/claims/role, but accessed through code using string constants, such as


public static class CustomClaimTypes
{
     public const string Role = "http://thefreakparade.com/claims/role";
     //...more...
}

and therefore accessed in code like this:


var claim = new Claim(CustomClaimTypes.AgeInYears,43);

The expression evaluator will interperet something like AgeInYears to be a variable, and the name AgeInYears won’t naturally correspond to anything, because it’s really just a property name, the real claim is represented by a URI that would be far too ugly to stick in an expression. The solution is to give the expression evaluator a little help when evaluating variables, like so:


public bool Authorize(IList<iclaim> claims,string authExpression)
{
    var context = new ExpressionContext(claims);

    context.ResolveUnknownVariable +=
        (sender, args) =>
            {
               args.VariableValue =
                 claims.GetClaimValue(_claimAliases[args.VariableName]);

            };

    context.ResolveMissingFunction +=
        (sender, args) =>
            {
                if (args.FunctionName.Equals("IsInRole",StringComparison.OrdinalIgnoreCase))
                {
                    args.Function = (funcArgs) => IsInRole(claims,funcArgs);
                }
            };

    return ExpressionEvaluator.EvaluateExpression(authExpression,context);    

}

This method was modified a little from the actual sample to the purpose of clarity, but the general idea is the same. Also demonstrated is the technique required to add an IsInRole method to the expression language. The actual implementation of the IsInRole functionality is implemented off screen, see the sample for the actual code. This method also relies on a hashtable called _claimAliases being pre-populated with a mapping between the URI of a claim type and the friendly name the expression language will use. In the sample app, I simply used reflection to load the alias table with a mapping between the field name of each const and the actual URI.

Now, if you simple use the expression evaluator an call Authorize from within your service methods, like this:


public void MyServiceMethod()
{
    if (AuthorizationHelper.Authorize(
           CurrentUser.Claims,"AgeInYears >= 21 and IsInRole('Premium User')" == false)
    {
	//Whatever you do when someone isn't authorized. Throw a not authorized exception? Return a fault code?
    }

    //Implement your service method here, your user is old enough and has paid their money
}

Then all we added with the dynamic expression was complexity - your rules are still defined inline in your code. What you really want is a syntax like this:


public void MyServiceMethod()
{
    if (AuthorizationManager.Authorize(CurrentUser.Claims,Permissions.CanAccessServiceMethod) == false)
    {
        //no access
    }
    //service code
}

Where Permissions.CanAccessServiceMethod will key into a persistent authorization rule store such as a config file or database, so that the rule expressions themselves can be dynamically loaded at runtime and therefore modified outside of the code. The sample application takes advantage of a very simplified implementation of the Repository pattern and introduces an IAuthorizationRuleRepository to solve that issue. If you were really, really smart you could get to a syntax like this without much extra effort. Note this sample application does not quite go this far, but it shouldn’t be a stretch for you get there yourself if you care to:


[RequiresPermission(Permissions.CanAccessServiceMethod)]
public void MyServiceMethod()
{
    //service code
}

The only caveat with an attribute based approach is that access to your protected method is all or nothing. You can’t return a set of records filtered one way when one permission level is present, and another for a lower level of permission. But nothing would prevent you from mixing an attribute based approach with an inline-code based approach as appropriate.

Finally, here is a sample of the actual authorization syntax as implemented by the Identity at Rest sample application:


public List<monkey> ListAllMonkeys()
{
    //Only administrators can list all monkeys.
    //Everyone else can just list shaved monkeys.
    if (AuthorizeFor(
            Permissions.MonkeyShavingService.CanViewUnshavedMonkeys) == false)
    {
        return ListMonkeysByStatus(MonkeyStatus.ShavedClean.ToString());
    }

    return _monkeys;
}

And that’s about it. If you’ve made it this far, your very well aware that this post is describing a general approach to claims based authorization using an expression oriented DSL - the code samples listed here aren’t detailed enough to get you from point A to point B in an actual implementation. However, the included sample application, which is an evolution of the Identity At Rest sample application provided for this post, does provide an end to end application that fully implements the concepts discussed here. The sample comes with a “smart client” Winforms application that uses WCF to communicate with a remote  REST based API. All API calls are secured using the above described techniques.

I would be the last one to suggest that this approach is a “best practice” in managing claims based authorization, but it made sense to us and seems to work pretty well so far.  As always, I’d love to hear about any other approaches that you may be using.

Comments
Comments
Categories
DSL, Identity, Uncategorized
Comments rss Comments rss
Trackback Trackback

Another Free E-Book - Domain Driven Design Quickly

July 10, 2008

Yet another community gift - this time an e-book about Domain Driven Design. You can buy a print version but the PDF is free, and small enough to easily print out yourself and bind with a clip. The book is by the founder and editor of InfoQ.com, and is billed as a summary of Eric Evans (this one, not this one ) famous book, Domain Driven Design.  image At this rate I may never have to purchase another book again.

Comments
Comments
Categories
Uncategorized
Comments rss Comments rss
Trackback Trackback

Foundations of Programming - free ALT.NET e-book

June 27, 2008

I am constantly amazed (and humbled) by the generosity of time experts in this field of very, very busy people continue to demonstrate over and over again. I don’t know if other professions are the same way, but it really makes this one a pleasure to work in. Here is a free e-book by Karl Seguin of CodeBetter.com. I haven’t read it yet, but I very much look forward to it. From the TOC it looks like it will be a very useful resource.

You can get it here.

image

Comments
Comments
Categories
Uncategorized
Comments rss Comments rss
Trackback Trackback

Baby Stepping into MSIL - creating an "Event Recorder" using a DynamicMethod and Reflection.Emit

I’ve often been caught between two opposing forces - the desire to find some excuse to use Reflection.Emit to dynamically generate behavior, because it has a sort of magical quality about it, and on the other hand being completely intimidated by the strange and foreboding mysteries of IL. I finally found an excuse compelling enough to brave my fears and stick my toe in the water, and it wasn’t too bad.

The excuse to take the plunge was, as is often the case, laziness (or perhaps impatience). I had an interface with a blue million events on it, and I wanted create some unit tests that ensured all my little events were fired the right number of times, in the right order, with the right arguments, but I didn’t want to subscribe to all the events individually and set a bunch of flags, etc. etc. (BTW - I imagine this problem has been solved by superior minds - I didn’t spend much time looking)

[UPDATE] Here is a CodeProject article explaining how to do essentially the same thing as EventRecorder without using Reflection.Emit. Instead, an EventProxy intermediary class is used to store the EventName. http://www.codeproject.com/KB/cs/eventtracingviareflection.aspx 

The sample code, along with unit tests and a Windows Forms app demonstrating possible usage, can be found here.

Here is a typical usage:


[Test]
public void Recorder_Will_Record_Events()
{
    var source = new TestEventSource();
    using (var recorder = new EventRecorder(source))
    {
      source.FireSimpleEvent();
      source.FireSimpleEvent();
      source.FireEventWithCustomArgs("MyTestText");
      source.FireSimpleEvent();
      source.FireEventWithCustomArgs("NewTestText");

      Assert.That(recorder.EventHistory.Length, Is.EqualTo(5));

      Assert.That(((TestEventArgs) recorder.EventHistory[2].Args).LoveMe, Is.EqualTo("MyTestText"));
      Assert.That(((TestEventArgs) recorder.EventHistory[4].Args).LoveMe, Is.EqualTo("NewTestText"));

      Assert.That(recorder.GetInvocationsFor("SimpleEvent").Length, Is.EqualTo(3));
      Assert.That(recorder.GetInvocationsFor("EventWithCustomargs").Length, Is.EqualTo(2));
     }
}

What I wanted to do was "record" all the events that were fired on a particular object during the course of some transaction, and then test that all the events that fired were the ones I was expecting, and in the appropriate order. I figured I would achieve this by creating a class called EventRecorder that could take in its constructor any other non-null object. It would then loop through each event in the objects type, subscribe to that event, and when the event fired add the name of the event and the EventArgs to a collection I could examine later. Pretty simple.

I though this would be a simple matter of using some plain ol’ reflection, like this:


foreach (EventInfo evt in eventSource.GetType().GetEvents())
 {
 	evt.AddEventHandler(eventSource,
            new EventHandler(
		(sender,args)=>RecordEvent(evt.Name,args)));
 }

But alas, AddEventHandler expects a delegate that exactly matches the signature of the event, meaning if I have an event defined with EventHandler<CancelEventArgs>, it isn’t going to let me pass a plain EventHandler delegate. So what to do? Dynamically generate an event handler with the appropriate signature, of course, and emit a simple call to my RecordMethod. Essentially, we’ll be generating the equivalent of this:


private void HandleEvent(object sender,EventArgs<canceleventargs> args)
{
    this.RecordEvent(args,"NameOfTheEvent");
}

I found an MSDN article that looked like just the ticket. The technique presented uses the DynamicMethod class, which you can use to create an ad hoc method and fill it full of op-codes to tell it what to do. In this case, we wanted to instantiate a DynamicMethod that matches the signature of the event handler we want to subscribe to. Then we simply needed to emit the IL to call the RecordEvent method and pass in the appropriate arguments. In the code below, EventSource refers to the object whose events we’re subscribing to, and was passed in to the constructor of the EventRecorder class.


/// <summary>
/// This method crates a DynamicMethod matching the signature of
/// the delegate required by the passed in EventInfo. The method
/// will simply pass the arguments on to the RecordEvent method.
/// </summary>
/// <param name="evt"></param>
protected void BindToEvent(EventInfo evt)
{
    Type handlerType = evt.EventHandlerType;

    if (handlerType == null)
        throw new ArgumentException("No handler could be " +
                              " identified for " + evt.Name);

    Type[] handlerParams = GetDelegateParameterTypes(handlerType);

    //Not technically required, but may be helpful if an exception is thrown
    String dynamicHandlerName =
        String.Format("EventSource_{0}", evt.Name);

    var handlerDef = new DynamicMethod(dynamicHandlerName,
                                       typeof(void),
                                       handlerParams,
                                       typeof (EventRecorder));

    MethodInfo recordEvent =
        typeof (EventRecorder).GetMethod(
            "RecordEvent",
             BindingFlags.Instance | BindingFlags.NonPublic);

    ILGenerator ilgen = handlerDef.GetILGenerator();

    //load 'this' onto the stack
    ilgen.Emit(OpCodes.Ldarg_0);

    //load the second argument (EventArgs) onto the stack
    //We're not using the sender parameterf of the delegate,
    //so we skip emitting OpCodes.Ldarg_1
    ilgen.Emit(OpCodes.Ldarg_2);

    //Load the name of the event onto the stack
    ilgen.Emit(OpCodes.Ldstr, evt.Name);

    //Call the RecordEvent method, passing the two loaded argumetns
    //EventArgs args and String name
    ilgen.Emit(OpCodes.Callvirt, recordEvent);

    //Return control
    ilgen.Emit(OpCodes.Ret);

    //Create a delegate out of this new handler, binding to the current
    //instance as the target
    Delegate handler = handlerDef.CreateDelegate(handlerType,this);

    try
    {
        //Register the new delegeate with the event on the event source
        evt.AddEventHandler(EventSource, handler);
    }
    catch (Exception ex)
    {
        //Some COM objects don't like this method. In production, you wouldn't
        //eat this error like this, but for my example, I wanted to show events
        //on the WebBrowser control, and certain events of WebBrowser
        //don't appreciate this dynamic approach. So...
    }

    //record this handler so we can get to it later
    //when we need to remove our registration from
    //the event source during dispose
    _handlers.Add(evt.Name, new EventRef(handler,evt));
}

/// <summary>
/// Extract the signature of the event's delegate
/// </summary>
/// <param name="d"></param>
/// <returns></returns>
private static Type[] GetDelegateParameterTypes(Type d)
{
    if (d.BaseType != typeof (MulticastDelegate))
        throw new ApplicationException(
            d.Name + " is not a delegate.");

    MethodInfo invoke = d.GetMethod("Invoke");

    ParameterInfo[] parameters = invoke.GetParameters();

    //Allocate an extra slot, see below for why
    var typeParameters = new Type[parameters.Length+1];

    for (int i = 0; i < parameters.Length; i++)
    {
        typeParameters[i+1] = parameters[i].ParameterType;
    }

    //This is an extremely important step - we need to inject the type
    //of EventRecorder because we will be using EventRecorder as the Target
    //of the dynamic delegate that we create using the DynamicMethod. When
    //you go to convert your emitted MSIL to an actual delegate using DynamicMethod.CreateDelegate,
    //the first argument of the signature MUST match the target object you are binding
    //the delegate to.
    typeParameters[0] = typeof (EventRecorder);

    return typeParameters;
}

/// <summary>
/// The internal method that gets called by the dynamically
/// generated delegates we are using to bind to the EventSource's
/// events. This method will get called once for every event that fires
/// on the EventSource.
///
/// <param name="args"></param>
/// <param name="eventName"></param>
protected virtual void RecordEvent(EventArgs args, string eventName)
{
    EventInfo evt = _handlers[eventName].Event;

    if (evt != null)
    {
        var history = new EventInvocation { Args = args, Event = evt };
        _eventHistory.Add(history);
        OnEventRecorded(history);
    }
}

IL is pretty close to the machine, relative to C#, so it’s entirely stack based. You load arguments onto the call stack, then perform an operation, such as calling a method. If you call a method, and the method has a signature with arguments, the arguments for the method signature are popped off the stack and consumed.

In this example we’re generating a dynamic method with a signature of two visible arguments - (object,MyEventArgs) - but we’re calling a method (RecordEvent) with a slightly different signature (EventArgs,string). We can discard the "object" argument of the dynamic method, which we do simply by not loading it onto the stack, which is why we don’t emit the opcode Ldarg_1, but we need to load the EventArgs and a string.

Looking at my source code it doesn’t quite add up though, because you can see I’m loading argument 0 (Ldarg_0) which looks like it should be "object" based on the dynamic method signature and argument 2 (Ldarg_2) which doesn’t even seem like it should exist, as the signature is (object,EventArgs) - only two arguments. Well, it turns out that all instance methods require a 0 position argument that is "this" - this argument is inserted by the compiler so you never see it, but when you say "this.DoSomething()" in your code, in IL method signature that gets created is DoSomething(MyType this). That means our call to "RecordEvent(EventArgs,string)" really looks like this: "RecordEvent(EventRecorder,EventArgs,string)", which means we need to load 3 variables onto the stack, which we do:

Ldarg_0 = this

//Ldarg_1 = object - not needed

Ldarg_2 = EventArgs

Ldsstr = EventInfo.Name

NOT calling Ldarg_1 discards the object part of the dynamic method signature, which is OK, because that just represents EventSource anyway, and we have a reference to that already.

One important thing to note, though, is that when calling CreateDelegate on DynamicMethod it is critical to pass in "this" as the target - otherwise when the method you generated tries to access member variables, you’ll get illegal memory access errors. Also subtle, if you are creating a dynamic method that you intend to bind to an instance of an object, then the DynamicMethod needs to be created using the secret, full signature of MyMethod(EventRecorder,object,EventArgs) NOT just MyMethod(object,EventArgs) as you would expect. You can see this being taken care of in the GetDelegateParameterTypes method. This piece of info was not in the MSDN sample, and was a just a joy to figure out :)

By the way - a great way to figure out just what IL you need is to write the method you are hoping to generate, compile it, then view the IL in ILDASM.exe. Then you can either blindly translate the IL into Opcode.xxx calls, or you try to understand why it is doing what it is doing and modify according to your needs, but I probably never would have figured out the Ldarg_0 / Ldarg_2 mystery on my own - ILDASM saved my butt.

I need to find a better way of debugging this stuff, but the fact of the matters is that once you see what is going on, IL isn’t really any more complicated than anything else, it is just far more verbose and cryptic when you get it wrong :)

The rest of EventRecorder is nothing special. The sample includes unit tests and a simple windows forms example.

Here are some resources:

DynamicMethod.CreateDelegate Method

How to hook up a delegate using reflection

Reflection.Emit tidbits

Introduction to creating types with Reflection.Emit, DymamicMethod

Comments
Comments
Categories
Uncategorized
Comments rss Comments rss
Trackback Trackback

nServiceBus Management Extensions - new CodePlex project

May 16, 2008

I just launched a new open source project on CodePlex, NSB Management Extensions. This purpose of this project is to provide endpoint management, such as endpoint heartbeat monitoring & node performance monitoring, which exists in the initial release, as well as some more advanced services such as service/endpoint repositories, event broker with server-side subscription rules, a processing pipeline for the MSMQ Transport, etc.

The project can be found here: http://www.codeplex.com/NSBManagement

Comments
Comments
Categories
Uncategorized
Comments rss Comments rss
Trackback Trackback

Unit Testing Custom .NET Configuration Classes

May 15, 2008

I am currently in the process of writing some custom .NET Configuration classes, such as custom ConfigurationHandler implementations, ConfigurationElementCollection, etc. Configuration classes need to be tested just like any other code, especially if they contain any behavior beyond the simple mapping of an XML property to a class property. It turns out the .NET Configuration API makes this pretty easy:

 

    [TestFixture]
    public class ConfigurationTestFixture
    {
        [Test]
        public void TestCustomConfig()
        {
            var cfg = GetTestConfiguration();
            Assert.That(cfg, Is.Not.Null);

            var mySection = cfg.GetSection("mySection") as mySection;
            Assert.That(mySection, Is.Not.Null);
            Assert.That(mySection.CustomProp,Is.EqualTo("configuredValue"));
            ...

        }

        private System.Configuration.Configuration GetTestConfiguration()
        {
            var map = new ExeConfigurationFileMap()
                          {
                              ExeConfigFilename =
                              Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                              "TestApp.config")
                          };

            return ConfigurationManager.OpenMappedExeConfiguration(
                    map, ConfigurationUserLevel.None);
        }

 

For this to work you’ll need a configuration file with the appropriate XML to test your classes stored at the root of your test project with the Copy To Output Directory property set to Copy If Newer. You could use any path to create your ExeConfigurationFileMap, but for me putting the file at the root seemed the easiest solution.

image

Comments
Comments
Categories
Uncategorized
Comments rss Comments rss
Trackback Trackback

.NET Configuration - THE article on customizing the configuration of your app

In looking for a palatable way to add configuration file support to some components I’m writing I looked at a number of articles on the topic, all of which discussed some interesting aspect of the configuration. This article, however, covers it all. It is a little long, but well organized so you can find just the parts you need. If you ever engage in creating a configuration section for your .NET 2.0+ app, this is the reference.

http://www.codeproject.com/KB/dotnet/mysteriesofconfiguration.aspx

 

That being said, here’s a totally different approach to configuration using the XML Serializer. You would lose some validation capabilities, but you gain virtually unlimited flexibility in your object model and you can write whatever simple configuration model you like without worrying about the configuration namespace classes.

http://www.15seconds.com/issue/040504.htm

Comments
Comments
Categories
Uncategorized
Comments rss Comments rss
Trackback Trackback

The Line Between Web App and Desktop App Begins To Blur

April 29, 2008

And….once the line begins to blur we all know it will eventually go away all together.

Mozilla is getting into the act tool.

Mozilla Prism

Also, search google for Silverlight + Desktop Application and you’ll get to the Silverlight overview. Silverlight Overview. An interesting section can be found at the end of the overview.

“Expression Design is a professional illustration and graphic design tool that lets you build compelling elements for both Web and desktop application user interfaces. Creating rich visual elements for Silverlight applications is made simple using Expression Design. XAML is automatically generated for elements that are supported on the Silverlight platform and all other visuals are automatically rasterized and included as bitmap objects.”

You can use Expression Blend and xaml to create desktop executables. The installing Expression Blend also installs several sample applications that run as exes. So soon if not already we should be able to create an app we can run as a web page and recompile to run as a executable.

Comments
Comments
Categories
Uncategorized
Comments rss Comments rss
Trackback Trackback

Free WebEx, GoToMeeting alternative

April 12, 2008

I happened across an online GoToMeeting, WebEx replacement that has an open source on premise version or a free hosted version that somehow doesn’t require meeting attendees to download plug ins. This might we worth checking out.

 

Comments
Comments
Categories
Uncategorized
Comments rss Comments rss
Trackback Trackback

Client Side Templating with jQuery

April 10, 2008

A method for using the jQuery library to do AJAX data replacements inside an existing html structure.

http://west-wind.com/weblog/posts/300754.aspx

Comments
Comments
Categories
Uncategorized
Comments rss Comments rss
Trackback Trackback

Subscribe

Calendar

January 2009
M T W T F S S
« Nov    
 1234
567891011
12131415161718
19202122232425
262728293031  

Recent Posts

  • You Can’t Fill an Imaginary Hole
  • I don’t know but I’ve been told, ETL is gettin’ mighty old. BAM! BAM! EDA! I want my data right away!
  • Be Prepared To Be Surprised
  • Google Chrome, I could kiss you! (Or, multi-process browsers are a really good idea)
  • New Open Source .NET CMS/EPS Platform Released Today: Sense/Net 6.0 Beta 1

Recent Comments

  • Ashwani on Rule Based Access Control using an Expression Evaluator
  • Richers Blog on Identity’s new Identity - Part 3, The Technology
  • sandra on ESB’s for the Microsoft (.NET) Platform
  • nstults on Content Management Systems (CMS) for the .NET Platform
  • Adz on Content Management Systems (CMS) for the .NET Platform

Tags

TDD Testing

Meta

  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org
rss Comments rss valid xhtml 1.1 design by jide powered by Wordpress get firefox