Session Scoped Bindings With Ninject 2

An entry about inversion of control | ninject | asp.net | asp.net mvc Publication date 2. June 2010 18:33

Ninject 2 comes out of the box with a set of standard scoping options for activations: transient, singleton, threaded etc. There’s also an ASP.NET specific “request” scope, which ensures that all activations for a binding returns the same instance throughout one request. However, there’s no session scope (at least not that I could dig up), so if you want a scope such that activations of a binding returns the same instance throughout the lifetime of an entire ASP.NET session, you’ll have to roll your own.

Googling for a while, I couldn’t find anyone having blogged about this before. Which I find weird, because surely this is a common scoping requirement for web applications? I guess everyone is too busy twittering these days to blog much (not me though, nu uh :-p).

Anyways, we can roll our own solution for this fairly easily using the InScope() method, which Nate Kohari explains how works like this:

The object returned by the callback passed to InScope() becomes the "owning"
object of instances activated within the scope. This has two meanings:

1. If the callback returns the same object for more than one activation,
Ninject will re-use the instance from the first activation.

2. When the object returned from the callback is garbage collected, Ninject
will deactivate ("tear down", call Dispose(), etc.) any instances associated
with that object.

Armed with this knowledge, all we need to do is ensure that InScope is given a callback that returns the same, unique object for each session. My first idea was to simply pass it HttpContext.Current.Session – but ASP.NET is built so that it rebuilds the HttpContext object (and the Session bag) for each request, so this essentially makes the scoping a request scope. So we’ll need to make things a little bit more complicated:

public static class NinjectSessionScopingExtention

{

    public static void InSessionScope<T>(this IBindingInSyntax<T> parent)

    {

        parent.InScope(SessionScopeCallback);

    }

 

    private const string _sessionKey = "Ninject Session Scope Sync Root";

 

    private static object SessionScopeCallback(IContext context)

    {

        if (HttpContext.Current.Session[_sessionKey] == null)

        {

            HttpContext.Current.Session[_sessionKey] = new object();

        }

 

        return HttpContext.Current.Session[_sessionKey];

    }

}

Here we’re essentially using the ASP.NET session bag to store an object throughout the lifetime of the session, which we can then use as the scope owner. And that’s it, we can now set up bindings InSessionScope().

Check out my session on the Dependency Inversion Principle (track 7, day 3) at NDC 2010 in a couple of weeks for an in depth discussion on taking full advantage of modern IOC containers scoping features.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Resolving relative URL’s from JavaScript

An entry about javascript | asp.net | asp.net mvc Publication date 22. August 2009 14:50

On the server side of an ASP.NET or ASP.NET MVC application, we’re used to working with relative URL’s in the style of “~/Images/logo.png”. This makes our application safely deployable to virtual directories within IIS applications without messing up the URL’s. However, what do we do if we need the same functionality in our JavaScript?

I’m solving this by sticking the following script in my Site.Master file:

Url = function() { }

Url.prototype =
{
    _relativeRoot: '<%= ResolveUrl("~/") %>',

    resolve: function(relative) {
        var resolved = relative;
        if (relative[0] == '~') resolved = this._relativeRoot + relative.substring(2);
        return resolved;
    }
}

$Url = new Url();

Now, anywhere I need to resolve a relative url in a script, I can do this:

var logoUrl = $Url.resolve("~/Images/logo.png");

Currently rated 4.6 by 5 people

  • Currently 4.6/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Constructor Injection for ASP.NET MVC Model Binders

An entry about asp.net mvc | inversion of control Publication date 18. April 2009 13:23

My last post was about how to let your IOC container manage ASP.NET MVC action filters. This time, let’s look at how to do the same with model binders.

Last month, Jimmy Bogard shared his SmartBinder implementation which solved this. For my requirements however, Jimmy’s implementation has one show-stopper: By injecting all the model binders into his custom binder resolver, he is essentially limiting the lifetime of binders to singleton behavior, since the resolver itself has to live as a singleton within ASP.NET MVC’s model binder dictionary. I think that a better solution would be to let the custom binder resolver forward binder resolution to the IOC container on an ad-hock basis. Here’s my GenericBinderResolver which does that:

public class GenericBinderResolver : DefaultModelBinder

{

    private readonly ICanResolveDependencies _resolver;

    private static readonly Type BinderType = typeof(ModelBinder<>);

 

    public GenericBinderResolver(ICanResolveDependencies resolver)

    {

        _resolver = resolver;

    }

 

    public override object BindModel(ControllerContext controllerContext,
                                     ModelBindingContext bindingContext)

    {

        Type genericBinderType = BinderType.MakeGenericType(bindingContext.ModelType);

 

        var binder = _resolver.Resolve(genericBinderType) as IModelBinder;

 

        if (null != binder) return binder.BindModel(controllerContext, bindingContext);

 

        return base.BindModel(controllerContext, bindingContext);

    }

}

Notice how the binder resolver builds a generic ModelBinder<T> type from the model type, and asks the IOC container to resolve it (the container is abstracted by the ICanResolveDependencies interface). This way, the container is free to manage the lifetime of each model binder separately.

Binders are implemented by deriving from my generic ModelBinder<T> class:

public abstract class ModelBinder<T> : IModelBinder

{

    protected abstract T BindModel(ControllerContext controllerContext,
                                   ModelBindingContext bindingContext);

 

    object IModelBinder.BindModel(ControllerContext controllerContext, 
                                  ModelBindingContext bindingContext)

    {

        return BindModel(controllerContext, bindingContext);

    }

}

For example, here’s a model binder which gets an aggregate root from a domain service. This binder has to have a lifetime which is compatible with the per-request scope of the domain service it depends upon (note: I’ve simplified the binder a bit, removing validation etc).

public class PostModelBinder : ModelBinder<IPost>

{

    private readonly IBlogService _blogService;

 

    public PostModelBinder(IBlogService blogService)

    {

        _blogService = blogService;

    }

 

    protected override IPost BindModel(ControllerContext controllerContext,
                                       ModelBindingContext
bindingContext)

    {

        var request = controllerContext.HttpContext.Request;

 

        var postIdString = request["postId"];

 

        IPost post = null;

 

        if (!String.IsNullOrEmpty(postIdString))

        {

            var postId = Int32.Parse(postIdString);

            post = _blogService.FindPost(postId);

        }

 

        return post;

    }

}

Then, all I have to do is register the binder in my container (Ninject):

Bind<ModelBinder<IPost>>().To<PostModelBinder>().Using<RequestScopedBehavior>();

Currently rated 4.2 by 5 people

  • Currently 4.2/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Constructor Injection for ASP.NET MVC Action Filters

An entry about asp.net mvc | inversion of control Publication date 9. April 2009 11:50

ASP.NET MVC’s action filters allow you to execute some code before/after an action in a declarative manner, manipulating what goes into or comes out of the action. In essence, they are what’s called aspects in Aspect Oriented Programming; a way of encapsulating crosscutting concerns into reusable components. For example, instead of this:

public ActionResult SomeActionWhichRequiresAuthentication()

{

    if (!User.Identity.IsAuthenticated)

    {

        return RedirectToAction("Login", "Authentication");

    }

    else

    {

        // ...

    }

}

You’ll do this:

[Authorize]

public ActionResult SomeActionWhichRequiresAuthentication()

{

    // ...

}

However, a problem with ASP.NET MVC’s action filters is that there’s no support for having an IOC container manage them, which means that if I need to do something more complicated that requires calling into a domain service/repository for example, I cannot get these injected easily. Jeremy Skinner has a solution which enables property injection, but what I really want is constructor injection.

Solution: The Proxy Pattern

What I came up with, was to build a filter proxy. Using it looks like this:

[Filter(typeof(AuthorizationFilter))]

public ActionResult SomeActionWhichRequiresAuthentication()

{

    // ...

}

Internally, the FilterAttribute resolves the actual filter using the IOC container and forwards all its calls to it:

public class FilterAttribute : ActionFilterAttribute

{

    private readonly Type _actionFilterType;

    private IActionFilter _action;

 

    public FilterAttribute(Type actionFilterType)

    {

        _actionFilterType = actionFilterType;

    }

 

    public override void OnActionExecuting(ActionExecutingContext filterContext)

    {

        // resolve the action filter using the IOC container

        var container = (ICanResolveDependencies) HttpContext.Current.ApplicationInstance;

        _action = (IActionFilter)container.Resolve(_actionFilterType);

 

        _action.OnActionExecuting(filterContext);

        base.OnActionExecuting(filterContext);

    }

 

    public override void OnActionExecuted(ActionExecutedContext filterContext)

    {

        _action.OnActionExecuted(filterContext);

        base.OnActionExecuted(filterContext);

    }

}

This allows the IOC container to manage the instantiation and lifetime of the action filter. Note the assumption that the applications Application object (Global.asax) implements the ICanResolveDependencies interface, which essentially is an abstraction of the IOC container.

Currently rated 3.3 by 3 people

  • Currently 3.333333/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Ninject Module for ASP.NET MVC Controller Bindings

An entry about asp.net | asp.net mvc | inversion of control Publication date 25. August 2008 11:00

Setting up Ninject for use with ASP.NET MVC is dead easy; just use the integration API included in the MvcContrib project. However, registering all your controllers by hand can be tedious. Writing a custom module that automatically loads all the controllers in a given assembly is straight-forward, however:

public class ControllerModule : StandardModule
{
    private readonly Assembly _assembly;
 
    public ControllerModule(Assembly assembly)
    {
        _assembly = assembly;
    }
 
    public override void Load()
    {
        Type controllerType = typeof (IController);
 
        // find all types in the assembly that implement the IController interface
        foreach(Type type in _assembly.GetTypes())
        {
            if(controllerType.IsAssignableFrom(type))
            {
                string controllerName = type.Name;
 
                // strip the "Controller" suffix from name
                int cutIndex = controllerName.LastIndexOf("Controller");
                if(cutIndex > 0) controllerName = controllerName.Substring(0, cutIndex);
 
                // register controller binding
                Bind<IController>().To(type).Only(When.Context.Variable("controllerName").EqualTo(controllerName));
            }
        }
    }
}

And then your Global.asax will look like this:

public class GlobalApplication : HttpApplication
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 
        // *snip* route registration
    }
 
    protected void Application_Start()
    {
        RegisterRoutes(RouteTable.Routes);
        InitializeNinject();
    }
 
    public void InitializeNinject()
    {
        NinjectKernel.Initialize(new ControllerModule(Assembly.GetExecutingAssembly()));
        ControllerBuilder.Current.SetControllerFactory(typeof(NinjectControllerFactory));
    }
}

Happy days!

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Mapping a Checkbox To a Boolean Action Parameter in ASP.NET MVC

An entry about asp.net mvc Publication date 23. August 2008 13:38

Say you have some controller action that takes a boolean:

public ActionResult Login(string username, string password, bool rememberMe)
{
    // authenticate...
}

Now, you want to let the user set the “Remember me?” option using a check box:

<input type="checkbox" id="rememberMe" name="rememberMe" />
<label
for="rememberMe">Remember me?</label>

This won’t work! A checkbox is an input element, so when it gets posted, it posts its value - and a checkbox has the value ‘on’ by default (which cannot be parses as a boolean). You might think that we could use a bit of JavaScript trickery to change the value depending on the checked/unchecked state:

<input type="checkbox" id="rememberMe" name="rememberMe" 
onchange="this.value = this.checked ? 'true' : 'false'" />
<label
for="rememberMe">Remember me?</label>

This won’t work either! The semantics of a checkbox are a little bit different from what you may think; instead of posting a value indicating its checked/unchecked state, a checked checkbox posts whatever is in its ‘value’ attribute, and an unchecked checkbox posts nothing. This means that for an unchecked checkbox, ASP.NET MVC will not be able to find a value to map to the rememberMe parameter, and thus throw an exception at you.

The best way then to map a checkbox to a boolean action parameter, is to just set the value of the checkbox to ‘true’ (since it will only ever be used when the checkbox is checked):

<input type="checkbox" id="rememberMe" name="rememberMe" value="true" />
<label
for="rememberMe">Remember me?</label>

and then use a nullable boolean as the controller action parameter:

public ActionResult Login(string username, string password, bool? rememberMe)
{
    // authenticate...
}

This way, you'll get a 'null' when "Remember me?" is unchecked, and true when it is checked.

Currently rated 5.0 by 9 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Powered by BlogEngine.NET 1.4.5.0

Welcome!

My name is Fredrik Kalseth, and this is my blog - thanks for visiting! I am fortunate enough to work with what I love for a living, and this blog is essentially the biproduct of that.

I work as a senior consultant for Capgemini, and am also an active participant in the Norwegian .NET community, as an avid attendee but also as a speaker (most recently at NNUG and MSDN Live).

As a developer, I have a wide circle of interest. My primary passion is for agile, test-driven development, with focus on best practices and clean code. That said, I also love to work on the frontend, especially with web development.

On Twitter? My handle is fkalseth. On LinkedIn? I`m there too.

NDC 2010

The conference to attend this summer happens June 16th-18th in Oslo, Norway. Are you going? Be sure to catch my talk on AOP while you're there!

 

Disclaimer

This is a personal blog; any opinions expressed here are my own and do not necessarily reflect those of my employer. All content herein is my own original creation, and as such is protected by copyright law. Unless otherwise stated, all source code posted on this blog is freely usable under the Microsoft Permissive License.

What Readers Talk About

Comment RSS