mikeobrien.net Curriculum Vitae Blog Lab


Tuesday, December 20, 2011

JavaScript Prototyping Reference

I’ve had problems remembering what is actually happening when working with constructor functions and prototyping. I created the following table to demonstrate what's going on. If I’m missing something please let me know as I’m not a JavaScript ninja by any means.

A couple of things to note:


JavaScript
var x = function() {}
x = {
    // Only meaningful for constructors not functions.
    prototype: { 
        constructor: x,
        __proto__: Object.prototype
    },
    __proto__: Function.prototype
}
var Y = function(name) {
    // In a constructor 'this' refers to the
    // new object.
    this.name = name;
}

Y.prototype.printName = function() {
    // In a method, 'this' refers to the 
    // declaring object (Unless overridden).
    console.log(this.name);
}

var y = new Y('Fritz London'); 
Y = {
    // This will be set as the new objects prototype.
    prototype: { 
        constructor: Y,
        __proto__: Object.prototype,
        printName: function() {
            console.log(this.name);
        }
    },
    __proto__: Function.prototype
}

y = {
    __proto__: Y.prototype,
    name: 'Fritz London'
}
var z = { name: 'Richard Feynman' }
z = {
    __proto__: Object.prototype,
    name: 'Richard Feynman'
}
var a = { name: 'Werner Heisenberg' }

var createObject = function(prototype) {
    var F = function() {};
    F.prototype = prototype;
    return new F();
}

var b = createObject(a);
// Or the built in
var b = Object.create(a);
a = {
    __proto__: Object.prototype,
    name: 'Werner Heisenberg'
}

F = {
    prototype: a,
    __proto__: Function.prototype
}

b = {
    __proto__: a
}
CoffeeScript
class Parent
    constructor: ->
        @id = ++Parent.identity
    name: 'Niels Bohr'
    @identity: 0
function Parent() {
    this.id = ++Parent.identity;
}
Parent.prototype.name = 'Niels Bohr';
Parent.identity = 0;

---

Parent = {
    prototype: { 
        constructor: Parent,
        __proto__: Object.prototype,
        name: 'Niels Bohr'
    },
    __proto__: Function.prototype,
    identity: 0
}
parent = new Parent()
parent = {
    __proto__: Parent.prototype,
    id: 1
}
class Child extends Parent
    url: 'http://www.google.com'
__extends(Child, Parent);
function Child() {
    Child.__super__.constructor.apply(this, arguments);
}
Child.prototype.url = 'http://www.google.com';

---

Child = {
    prototype: { 
        constructor: Child,
        __proto__: Parent,
        url: 'http://www.google.com'
    },
    __proto__: Function.prototype,
    // CoffeeScript generated property
    __super__: Parent.prototype
}
child = new Child()
child = {
    __proto__: Child.prototype,
    id: 1
}
backbone.js
// [backbone.js].extend(protoProps, classProps)
var Person = Backbone.Model.extend({
    constructor: function() {
        this.id = ++Person.identity;
    },
    name: 'Niels Bohr'
}, {
    identity: 0
});
Person = {
    prototype: {
        // If a constructor property is not 
        // specified, a new function is used  
        // that calls the parent constructor
        // in the context of the new object.
        constructor: protoProps.constructor,
        __proto__: Backbone.Model.prototype,
        name: 'Niels Bohr'
    },
    __proto__: Function.prototype,
    // Backbone added property
    __super__: Backbone.Model.prototype
    // Backbone attaches this to new objects
    extend: Backbone.Model.extend,
    identity: 0
}
underscore.js
var person = { id: 5 }
var a = { name: 'Werner Heisenberg' }
var b = { occupation: 'Physicist' }
_.extend(person, a, b);
person = {
    id: 5,
    name: 'Werner Heisenberg',
    occupation: 'Physicist'
}

Monday, December 19, 2011

Dissecting the output of the CoffeeScript class and extends keyword

CoffeeScript has a convenient way of emulating class and inheritance semantics via the class and extends keyword. I wanted to better understand what was happening under the covers so the following is an analysis of the transpiler output. We’ll look at a simple relationship between two CS “classes”:

class Parent
    constructor: ->
        @id = ++Parent.identity
    @identity: 0

class Child extends Parent
    url: 'http://www.google.com'

CS outputs the following (As of 1.2):

var Child, Parent;
var __hasProp = Object.prototype.hasOwnProperty, 
    __extends = function(child, parent) {/* discussed later */};

Parent = (function() {
    function Parent() {
        this.id = ++Parent.identity;
    }
    Parent.identity = 0;
    return Parent;
})();

Child = (function() {
    __extends(Child, Parent);
    function Child() {
        Child.__super__.constructor.apply(this, arguments);
    }
    Child.prototype.url = 'http://www.google.com';
    return Child;
)();

Some things I noted:

  • The CS transpiler builds the constructor functions in IIFE’s so we don’t clutter up the global object.
  • The CS “constructor” property is the body of the constructor function.
  • The CS @ prefix…
    • … refers to the new object only when used in the constructor.
    • … refers to the function object outside of the constructor (to declare “static” properties).
  • Properties not prefixed with the CS @ are prototype properties.
  • The “parent” constructor function can be executed in the context of the new child object. This happens automatically (As shown above) if the child does not explicitly declare a constructor. If the child object does supply a constructor (And you want to call the parent constructor) you will need to manually call super(…) in the child constructor with zero or more arguments.

Now lets take a look at the __extends method that is generated by CS. This method sets up the prototype chain and a property that links to the “parent” prototype.

var __hasProp = Object.prototype.hasOwnProperty;
var __extends = function(child, parent) { 
    for (var key in parent) {
         if (__hasProp.call(parent, key)) 
            child[key] = parent[key]; 
    } 
    function ctor() { 
        this.constructor = child; 
    } 
    ctor.prototype = parent.prototype; 
    child.prototype = new ctor; 
    child.__super__ = parent.prototype; 
    return child; 
};

Some things I noted:

  • All constructor function properties (Or “static” properties) are copied from the “parent” to the “child” constructor function.
  • An intermediate prototype object is created so that you can augment the “child’s” prototype without changing the “parent’s” prototype.
    • It’s prototype is the “parent” prototype.
    • It serves as the prototype of “child” objects.
    • It’s constructor is set to the “child” constructor function.
  • A special property called __super__ is created on the “child” constructor function. Evidentially CS likes to be backwards compatible as it doesn't make use of the relatively new Object.getPrototypeOf method. Calling super() in the CS constructor, as noted above, will make use of this property to call the “parent” constructor function.

From this we can see that CS sets up the prototype chain like so:

 

CoffeeScriptPrototypeChain

 

One more thing I was interested in was how the CS extends keyword compares to the underscore.js method of a similar name:

_.extend = function(obj) {
    each(slice.call(arguments, 1), function(source) {
        for (var prop in source) {
            if (source[prop] !== void 0) obj[prop] = source[prop];
        }
    });
    return obj;
};
Clearly they are very different. The underscore extend method basically does a mixin as it simply copies properties from the source objects to the target object.

Prototyping in Lua

One of the hardest things to get my head around in JavaScript (Besides “this”) was prototyping. I wasn't sure if it was prototyping itself that was hard to grok (It seemed amazingly simple to me in principle) or if it was how JavaScript implemented it. I thought it would be an interesting exercise to explore how another prototypal language worked to see where the difficulty lay. So let’s take a look at how Lua implements prototyping (Disclaimer: I only have a passing knowledge of Lua so please excuse my naïveté).

Lua “tables” form the basis of objects. They are essentially hash tables, à la JavaScript objects. Prototyping in Lua is enabled by two actions; first setting the objects’ metatable (Which can be any table) and second, setting the prototype field in that metatable (Which is the __index field). Here is how it works (NB: see here about the use of colon vs. dot. Compare it to call/apply in JavaScript):

-- Create the prototype
Greeting = { hello = 'hello' }

function Greeting:say_hello()
    print(self.hello)
end

-- Create an object
lolcat = { hello = 'hai' }

-- Set the meta table (A table where metadata is held), in this case we’ll just set it to be the object itself
setmetatable(lolcat, lolcat)

-- Set the prototype
lolcat.__index = Greeting

Other than the setting of the metatable I’d have to say this is incredibly straight forward. You can encapsulate the creation logic into a constructor which simplifies the process:

-- Constructor
function Greeting:new(o)
    o = o or {}
    o.__index = self
    return setmetatable(o, o)
end

lolcat = Greeting:new{ hello = 'hai' }

-- https://github.com/silentbicycle/lunatest
assert_equal('hai', lolcat.hello)

Although prototyping still presents a mental shift for me the Lua approach feels much cleaner and simpler. I find the dot/colon approach (mentioned above) much cleaner as well.

Saturday, June 25, 2011

Welcome to the FubuMVC Cafeteria

I was wondering what FubuMVC had wired up in the IoC container out-of-the-box and it happens to be quite a bit. Here is a dump of the container configuration (Using the spark view engine):

PluginType Description
Bottles.IActivator FubuMVC.Spark.SparkActivator, FubuMVC.Spark
FubuMVC.Core.Packaging.PackageFileActivator, FubuMVC.Core
FubuMVC.Core.Content.ScriptGraphConfigurationActivator, FubuMVC.Core
FubuCore.Binding.AggregateDictionary FubuCore.Binding.AggregateDictionary
FubuCore.Binding.IBindingContext FubuCore.Binding.BindingContext, FubuCore
FubuCore.Binding.ICollectionTypeProvider FubuCore.Binding.DefaultCollectionTypeProvider, FubuCore
FubuCore.Binding.IConverterFamily  
FubuCore.Binding.IModelBinder  
FubuCore.Binding.IModelBinderCache FubuCore.Binding.ModelBinderCache, FubuCore
FubuCore.Binding.IObjectResolver FubuMVC.Core.Diagnostics.Tracing.RecordingObjectResolver, FubuMVC.Core
FubuCore.Binding.IPropertyBinder  
FubuCore.Binding.IPropertyBinderCache FubuCore.Binding.PropertyBinderCache, FubuCore
FubuCore.Binding.IRequestData FubuMVC.Core.Diagnostics.Tracing.RecordingRequestData, FubuMVC.Core
FubuCore.Binding.ISmartRequest FubuMVC.Core.Runtime.FubuSmartRequest, FubuMVC.Core
FubuCore.Binding.IValueConverterRegistry FubuCore.Binding.ValueConverterRegistry, FubuCore
FubuCore.Binding.ObjectResolver FubuCore.Binding.ObjectResolver, FubuCore
FubuCore.IDisplayFormatter FubuCore.DisplayFormatter, FubuCore
FubuCore.IFileSystem FubuCore.FileSystem, FubuCore
FubuCore.IObjectConverter FubuCore.ObjectConverter, FubuCore
FubuCore.ITypeResolver FubuCore.TypeResolver, FubuCore
FubuCore.Reflection.ITypeDescriptorCache FubuCore.Reflection.TypeDescriptorCache, FubuCore
FubuCore.Reflection.TypeDescriptorCache FubuCore.Reflection.TypeDescriptorCache
FubuMVC.Core.Behaviors.IJsonReader FubuMVC.Core.Behaviors.JavaScriptJsonReader, FubuMVC.Core
FubuMVC.Core.Conneg.IFormatter FubuMVC.Core.Conneg.JsonFormatter, FubuMVC.Core
FubuMVC.Core.Conneg.XmlFormatter, FubuMVC.Core
FubuMVC.Core.Conneg.IMediaProcessor`1<T> FubuMVC.Core.Conneg.MediaProcessor`1, FubuMVC.Core
FubuMVC.Core.Content.IContentFolderService FubuMVC.Core.Content.ContentFolderService
FubuMVC.Core.Content.IContentRegistry FubuMVC.Core.Content.ContentRegistryCache, FubuMVC.Core
FubuMVC.Core.Content.IMimeTypeProvider FubuMVC.Core.Content.DefaultMimeTypeProvider
FubuMVC.Core.CurrentRequest Instance is created by Func<object> function:System.Func`2[StructureMap.IContext,FubuMVC.Core.CurrentRequest]
FubuMVC.Core.Diagnostics.DiagnosticsIndicator FubuMVC.Core.Diagnostics.DiagnosticsIndicator
FubuMVC.Core.Diagnostics.IDebugDetector FubuMVC.Core.Diagnostics.DebugDetector, FubuMVC.Core
FubuMVC.Core.Diagnostics.IDebugReport FubuMVC.Core.Diagnostics.DebugReport, FubuMVC.Core
FubuMVC.Core.Diagnostics.IRequestHistoryCache FubuMVC.Core.Diagnostics.RequestHistoryCache, FubuMVC.Core
FubuMVC.Core.Diagnostics.Tracing.BehaviorTracer FubuMVC.Core.Diagnostics.Tracing.BehaviorTracer, FubuMVC.Core
FubuMVC.Core.Diagnostics.Tracing.DiagnosticBehavior FubuMVC.Core.Diagnostics.Tracing.DiagnosticBehavior, FubuMVC.Core
FubuMVC.Core.IEndpointService FubuMVC.Core.EndpointService, FubuMVC.Core
FubuMVC.Core.Packaging.IPackageFiles FubuMVC.Core.Packaging.PackageFilesCache, FubuMVC.Core
FubuMVC.Core.Registration.BehaviorGraph FubuMVC.Core.Registration.BehaviorGraph
FubuMVC.Core.Registration.Querying.IChainResolver FubuMVC.Core.Registration.Querying.ChainResolver, FubuMVC.Core
FubuMVC.Core.Routing.IRoutePolicy FubuMVC.Core.Routing.StandardRoutePolicy, FubuMVC.Core
FubuMVC.Core.Runtime.IBehaviorFactory FubuMVC.StructureMap.PartialBehaviorFactory, FubuMVC.StructureMap
FubuMVC.Core.Runtime.IFubuRequest FubuMVC.Core.Diagnostics.Tracing.RecordingFubuRequest, FubuMVC.Core
FubuMVC.Core.Runtime.IJsonWriter FubuMVC.Core.Runtime.JsonWriter, FubuMVC.Core
FubuMVC.Core.Runtime.IOutputWriter FubuMVC.Core.Diagnostics.RecordingOutputWriter, FubuMVC.Core
FubuMVC.Core.Runtime.IPartialFactory FubuMVC.Core.Runtime.PartialFactory, FubuMVC.Core
FubuMVC.Core.Runtime.ISessionState FubuMVC.Core.Runtime.SimpleSessionState, FubuMVC.Core
FubuMVC.Core.Runtime.IStreamingData FubuMVC.Core.Runtime.StreamingData, FubuMVC.Core
FubuMVC.Core.Security.IAuthenticationContext FubuMVC.Core.Web.Security.WebAuthenticationContext, FubuMVC.Core
FubuMVC.Core.Security.IAuthorizationFailureHandler FubuMVC.Core.Security.DefaultAuthorizationFailureHandler, FubuMVC.Core
FubuMVC.Core.Security.IAuthorizationPolicyExecutor FubuMVC.Core.Diagnostics.Tracing.RecordingAuthorizationPolicyExecutor, FubuMVC.Core
FubuMVC.Core.Security.IAuthorizationPreviewService FubuMVC.Core.Security.AuthorizationPreviewService, FubuMVC.Core
FubuMVC.Core.Security.IChainAuthorizor FubuMVC.Core.Security.ChainAuthorizor, FubuMVC.Core
FubuMVC.Core.Security.IEndPointAuthorizor FubuMVC.Core.Security.NulloEndPointAuthorizor
FubuMVC.Core.Security.IEndPointAuthorizorFactory FubuMVC.Core.Security.EndPointAuthorizorFactory, FubuMVC.Core
FubuMVC.Core.Security.ISecurityContext FubuMVC.Core.Web.Security.WebSecurityContext, FubuMVC.Core
FubuMVC.Core.SessionState.IFlash FubuMVC.Core.SessionState.FlashProvider, FubuMVC.Core
FubuMVC.Core.SessionState.IRequestDataProvider FubuMVC.Core.SessionState.RequestDataProvider, FubuMVC.Core
FubuMVC.Core.UI.Configuration.IElementNamingConvention FubuMVC.Core.UI.Configuration.DefaultElementNamingConvention, FubuMVC.Core
FubuMVC.Core.UI.ICssLinkTagWriter FubuMVC.Core.UI.CssLinkTagWriter, FubuMVC.Core
FubuMVC.Core.UI.IPartialInvoker FubuMVC.Core.UI.PartialInvoker, FubuMVC.Core
FubuMVC.Core.UI.Scripts.IScriptTagWriter FubuMVC.Core.UI.Scripts.BasicScriptTagWriter, FubuMVC.Core
FubuMVC.Core.UI.Scripts.ScriptGraph FubuMVC.Core.UI.Scripts.ScriptGraph
FubuMVC.Core.UI.Security.IFieldAccessRightsExecutor FubuMVC.Core.UI.Diagnostics.RecordingFieldAccessRightsExecutor, FubuMVC.Core
FubuMVC.Core.UI.Security.IFieldAccessService FubuMVC.Core.UI.Security.FieldAccessService, FubuMVC.Core
FubuMVC.Core.UI.Tags.ITagGenerator`1<T> FubuMVC.Core.UI.Tags.TagGenerator`1, FubuMVC.Core
FubuMVC.Core.UI.Tags.TagProfileLibrary FubuMVC.Core.UI.Tags.TagProfileLibrary
FubuMVC.Core.Urls.IUrlRegistry FubuMVC.Core.Urls.UrlRegistry, FubuMVC.Core
FubuMVC.Core.Urls.IUrlTemplatePattern FubuMVC.Core.Urls.NulloUrlTemplate, FubuMVC.Core
FubuMVC.Core.View.Activation.IPageActivationRules FubuMVC.Core.View.Activation.PageActivationRuleCache, FubuMVC.Core
FubuMVC.Core.View.Activation.IPageActivationSource  
FubuMVC.Core.View.Activation.IPageActivator FubuMVC.Core.View.Activation.PageActivator, FubuMVC.Core
FubuMVC.Core.View.Activation.PageActivationRuleCache FubuMVC.Core.View.Activation.PageActivationRuleCache, FubuMVC.Core
FubuMVC.Spark.Rendering.IRenderStrategy FubuMVC.Spark.Rendering.NestedRenderStrategy, FubuMVC.Spark
FubuMVC.Spark.Rendering.AjaxRenderStrategy, FubuMVC.Spark
FubuMVC.Spark.Rendering.DefaultRenderStrategy, FubuMVC.Spark
FubuMVC.Spark.Rendering.IViewEntryProvider FubuMVC.Spark.Rendering.ViewEntryProviderCache, FubuMVC.Spark
FubuMVC.Spark.Rendering.IViewModifier FubuMVC.Spark.Rendering.PageActivation, FubuMVC.Spark
FubuMVC.Spark.Rendering.SiteResourceAttacher, FubuMVC.Spark
FubuMVC.Spark.Rendering.ContentActivation, FubuMVC.Spark
FubuMVC.Spark.Rendering.OnceTableActivation, FubuMVC.Spark
FubuMVC.Spark.Rendering.OuterViewOutputActivator, FubuMVC.Spark
FubuMVC.Spark.Rendering.NestedViewOutputActivator, FubuMVC.Spark
FubuMVC.Spark.Rendering.ViewContentDisposer, FubuMVC.Spark
FubuMVC.Spark.Rendering.NestedOutputActivation, FubuMVC.Spark
FubuMVC.Spark.Rendering.IViewModifierService FubuMVC.Spark.Rendering.ViewModifierService, FubuMVC.Spark
FubuMVC.Spark.Rendering.NestedOutput FubuMVC.Spark.Rendering.NestedOutput, FubuMVC.Spark
FubuMVC.Spark.Rendering.ViewOutput FubuMVC.Spark.Rendering.ViewOutput, FubuMVC.Spark
FubuMVC.Spark.SparkModel.ITemplateRegistry FubuMVC.Spark.SparkModel.TemplateRegistry
Microsoft.Practices.ServiceLocation.IServiceLocator FubuMVC.StructureMap.StructureMapServiceLocator, FubuMVC.StructureMap
Spark.ISparkViewEngine Spark.SparkViewEngine
StructureMap.IContainer StructureMap.Container
System.Web.HttpContextBase System.Web.HttpContextWrapper, System.Web
System.Web.HttpRequestWrapper Instance is created by Func<object> function:System.Func`2[StructureMap.IContext,System.Web.HttpRequestWrapper]

Wednesday, April 20, 2011

Building a Better MVC Filter Attribute Provider

As I mentioned here the filter attribute design in MVC is terrible. That other post explains why so I’m not going to rehash. This post is about how we can do it better. I don’t really have anything against using the attributes to annotate an action or controller it’s mainly that MVC makes the attribute itself the filter. What if, instead, the attribute was simply a marker that said that a particular filter should be applied and allowed you to customize it:

public interface IFilterAttribute
{
    Type FilterType { get; }
    void InitializeFilter(object filter);
}

This interface specifies the filter type then a method to initialize the filter. We could then implement this interface on an attribute like so:

public class SecureAttribute : Attribute, IFilterAttribute
{
    private readonly bool _enabled;

    public SecureAttribute(bool enabled)
    {
        _enabled = enabled;
    }

    public Type FilterType { get { return typeof(SecureFilter); } }

    public void InitializeFilter(object filter)
    {
        ((SecureFilter) filter).Enabled = _enabled;
    }
}

This attribute allows us to turn security on and off on an action or controller. You can see that it specifies the type and initialization of the filter. The filter is nothing special; in this case it implements IMvcFilter so it can set the multiplicity (In this case we only want one filter to be applied) and IAuthorizationFilter for authentication. It is also setup to be constructor injected:

public class SecureFilter : IAuthorizationFilter, IMvcFilter
{
    private readonly IAuthenticationService _authenticationService;

    public bool Enabled { get; set; }

    public SecureFilter(IAuthenticationService authenticationService)
    {
        _authenticationService = authenticationService;
        Enabled = true;
    }

    public bool AllowMultiple { get { return false; } }
    public int Order { get; set; }

    public void OnAuthorization(AuthorizationContext filterContext)
    {
        if (Enabled && !_authenticationService.Authenticate())
        {
            // Access denied
        }
    }
}

Now our filter provider can look for this new interface, IFilterAttribute and create the filters from the information provided from the attribute:

public class FilterAttributeProvider : IFilterProvider
{
    private static readonly Dictionary<string, IEnumerable<FilterAttributeMetadata>> AttributeCache =
        new Dictionary<string, IEnumerable<FilterAttributeMetadata>>();

    private readonly Func<Type, object> _filterFactory;

    public FilterAttributeProvider(Func<Type, object> filterFactory)
    {
        _filterFactory = filterFactory;
    }

    public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        return GetFilterAttributes(actionDescriptor).Select(x => CreateFilter(x, _filterFactory));
    }

    private static IEnumerable<FilterAttributeMetadata> GetFilterAttributes(ActionDescriptor actionDescriptor)
    {
        IEnumerable<FilterAttributeMetadata> attributes;
        if (!AttributeCache.TryGetValue(actionDescriptor.UniqueId, out attributes))
        {
            attributes = LoadFilterAttributes(actionDescriptor);
            lock (AttributeCache) AttributeCache.Add(actionDescriptor.UniqueId, attributes);
        }
        return attributes;
    }

    private static IEnumerable<FilterAttributeMetadata> LoadFilterAttributes(ActionDescriptor actionDescriptor)
    {
        return actionDescriptor.GetCustomAttributes(typeof(IFilterAttribute), true).Cast<IFilterAttribute>().
                                Select(x => new FilterAttributeMetadata(x, FilterScope.Action)).
                   Union(actionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(IFilterAttribute), true).
                                Cast<IFilterAttribute>().
                                Select(x => new FilterAttributeMetadata(x, FilterScope.Controller)));
    }

    private static Filter CreateFilter(FilterAttributeMetadata filterMetadata, 
                                       Func<Type, object> filterFactory)
    {
        var filter = filterFactory(filterMetadata.Attribute.FilterType);
        filterMetadata.Attribute.InitializeFilter(filter);
        return new Filter(filter, filterMetadata.Scope, GetFilterOrder(filter));
    }

    private static int? GetFilterOrder(object filter)
    {
        var mvcFilter = filter as IMvcFilter;
        return mvcFilter != null ? mvcFilter.Order : (int?)null;
    }

    private class FilterAttributeMetadata
    {
        public FilterAttributeMetadata(IFilterAttribute attribute, FilterScope scope)
        { Attribute = attribute; Scope = scope; }

        public IFilterAttribute Attribute { get; private set; }
        public FilterScope Scope { get; private set; }
    }

    public interface IFilterAttribute
    {
        Type FilterType { get; }
        void InitializeFilter(object filter);
    }
}

Using the type on the attribute, the provider can create the filter with a factory passed into the constructor (Which would be our IoC container). Once the filter is created it is initialized by the InitializeFilter() method on the attribute. This completely decouples attributes from filters and allows us to constructor inject filters even when they are applied via attributes. So as an example lets say that we want to globally apply security but in some actions or controllers we want to turn it off so they are public. We can register the secure filter we defined above and our authentication service in our IoC container (In this example StructureMap):

public class MvcApplication : HttpApplication
{
    protected void Application_Start()
    {
        ObjectFactory.Configure(x =>
                                    {
                                        x.For<IAuthenticationService>().Use<AuthenticationService>();
                                        x.For<IAuthorizationFilter>().Use<SecureFilter>();
                                    });

        DependencyResolver.SetResolver(x => (x.IsAbstract || x.IsInterface) ?
                                                ObjectFactory.TryGetInstance(x) :
                                                ObjectFactory.GetInstance(x), 
                                       x => ObjectFactory.GetAllInstances(x).Cast<object>());

        FilterProviders.Providers.Add(new FilterAttributeProvider(ObjectFactory.GetInstance));
    }
}

Now our entire site requires authentication. For an action that we want public we can turn authentication off:

public class HomeController : Controller
{
    [Secure(false)]
    public ActionResult Index()
    {
        return View();
    }
}

We only allow one SecureFilter to be applied, so since the filter associated with the attribute has an “Action” scope it will take priority over the global filter which has a “Global” scope.

Monday, April 18, 2011

Creating an Overridable MVC3 Global Filter

The new global filters in MVC3 are a nice way to apply behavior globally. Sometimes though you’ll want to opt out an action or controller from that behavior. Lets take authentication as an example; we want everything to be secure by default but we may have individual controllers or actions that will be public. The following authorize attribute enables us to create a global filter and then override the global behavior where we need to:

// Make sure we specify that this attribute should only be specified once.
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class SecureAttribute : AuthorizeAttribute
{
    private readonly bool _enabled;

    // Default constructor with security enabled, used as a global filter
    public SecureAttribute()
    {
        _enabled = true;
    }

    // Attribute constructor
    public SecureAttribute(bool enabled)
    {
        _enabled = enabled;
    }

    protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
    {
        return !_enabled || AuthenticationService.Authenticate();
    }
}

A few things to note. First we need to specify that this attribute should only be applied once with the AttributeUsageAttribute. Under the covers the FilterAttribute class looks for this attribute to determine if multiple instances of the filter can exist. In the default constructor we specify the default behavior; in this case security being enabled. In our authorization method we can check to see if authentication is enabled and proceed accordingly.

Here we can register the global default. This filter will have a scope of “Global” which is a lower priority scope:

public class MvcApplication : HttpApplication
{
    protected void Application_Start()
    {
        GlobalFilters.Filters.Add(new SecureAttribute());
        // ...
    }
}

We can then override the default behavior where appropriate. The action attribute has a scope of “Action” which is a higher priority scope. So this filter will take precedence over the globally added one:

public class SomeController : Controller
{
    [Secure(false)]
    public ActionResult SomePublicAction()
    {
        return View();
    }
}

Friday, April 15, 2011

On Filters in MVC3

I’ve been digging into the new filter functionality in MVC3 and this is a brain dump of what I’ve learned and some thoughts.

Filters currently must implement one or more of these interfaces: IActionFilter, IResultFilter, IExceptionFilter, and IAuthorizationFilter. The IMvcFilter interface allows you to tack on some additional metadata like the sort order and multiplicity. There are a couple of convenience classes that make creating filter attributes easier: FilterAttribute, ActionFilterAttribute, AuthorizeAttribute, HandleErrorAttribute and a few more. FilterAttribute implements IMvcFilter and so provides that metadata out of the box. When deriving from any of these attribute classes its important to understand that disallowing multiple instances of a filter is accomplished by applying the AttributeUsageAttribute to your derived class and setting AllowMultiple to false. The FilterAttribute class looks for that attribute to determine multiplicity and exposes it through the IMvcFilter.AllowMultiple property.

Originally filters (Which is a terrible name BTW. What do they filter??) were applied as .NET attributes to actions or controllers. At the beginning of the request, the controller and action filter attributes were pulled from the action method and controller class and run. One thing to note is that .NET attributes are only created by the CLR once (they are essentially singletons) so every time you reflect them in a particular app domain you will get the same object instances. I think the whole attribute approach for filters is badly implemented. One of the problems is that if you want to inject dependencies into an filter you have to rig up property injection. Additionally since they are attributes, and essentially singletons, they cannot hold any request specific state. This may be fine for something like authentication but difficult for transaction management as you will not be able to use IoC to inject request specific dependencies. I think a better design would have been to make the attributes more like WCF behaviors where the attribute itself is not the filter but simply acts as a way to create the filter. But that’s neither here nor there.

Now moving on to MVC3; things have changed a bit. We now have this concept of the IFilterProvider interface. This interface has one method, GetFilters() which as you can probably guess returns filters. Filter providers are now the source of all filters. There are three filter providers registered out of the box:

  1. GlobalFilters.Filters: This is simply a place where you can ad-hoc register individual filters that will be applied globally. These should be stateless as they will be reused for each request.
  2. FilterAttributeFilterProvider: This provider uses reflection to pull filters applied as attributes to controller classes and action methods; it basically does the job that the pre MVC3 code did. So the filters that this provider returns are not global, they are scoped to the controller and action. Since they are attributes they are essentially singletons and will be reused for each request so they should be stateless. Also keep in mind that the FilterAttributeFilterProvider will only discover attributes that derive from FilterAttribute. So deriving from Attribute and then implementing a filter interface will not get your attribute picked up by this provider.
  3. ControllerInstanceFilterProvider: This provider allows the controller servicing the request to act as a filter (ee gads!).

MVC calls the FilterProviders.Providers.GetFilters() method, to aggregate all the filters from all the filter providers, for each individual request. You can also register your own filter providers by adding an instance of a type that implements IFilterProvider to the FilterProviders.Providers collection. FilterProviders wrap filters in the Filter class which adds some additional information such as the scope and order. You can override the order in the Filter class constructor if you are writing your own filter provider or extending an existing one. If you don’t pass in an order it will check and see if the filter implements IMvcFilter and get the order from there otherwise it defaults to -1. One interesting thing about the code that aggregates all these is that it removes duplicate filters for those filters that do not allow duplicates (Exposed by the IMvcFilter.AllowMultiple property). The way it determines which ones to remove is by sorting the filters by the order and then by the scope and preserving the first instance it encounters and rejecting the subsequent instances. This means that higher orders win and then within an order, narrower scopes will win (Which is actually a higher scope number).

This post demonstrates how to pull global filters from your favorite IoC container.



Creative Commons License