Autofac ASP.NET Web API (Beta) Integration

by Alex Meyer-Gleaves 8 March 2012 - 8:23 AM

With the beta release of ASP.NET MVC 4 and the ASP.NET Web API being released a few weeks ago, I decided it was about time to have a look at what the integration story would like for Autofac. The package is available for download on NuGet.

Install-Package Autofac.WebApi

While building the preview of the Web API integration I had the following goals in mind:

  • Ensure that it would work alongside the MVC integration without issues such as naming conflicts.
  • Support both the web hosting and self hosting scenarios in a single assembly.
  • Avoid taking dependencies on the System.Web.Http.SelfHost and System.Web.Http.WebHost assemblies (to help achieve the goal above).
  • Minimize the amount of configuration required to get up and running.
  • Provide a lifetime scope around each call to an API controller so that it and its dependencies are automatically disposed at the end of the call.

I had some concerns about how easy this would be given the two different modes of hosting that are supported. When self hosting the entry point is a WCF service, and when hosting in ASP.NET the entry point is a HTTP handler. My concern was that wrapping each call to the API controller in an Autofac lifetime scope would require two completely different mechanisms. Perhaps a HTTP module style implementation and WCF extension similar to those found in the existing MVC and WCF integrations. It turns out this was not the case and if you are keen on learning about the details I will discuss them after we have seen some example code (because everyone wants to see some code sooner rather than later).

Example Code

If you are hosting within ASP.NET your Application_Start method would look something like this:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    BundleTable.Bundles.RegisterTemplateBundles();

    var configuration = GlobalConfiguration.Configuration;
    var builder = new ContainerBuilder();

    // Configure the container with the integration implementations.
    builder.ConfigureWebApi(configuration);

    // Register API controllers using assembly scanning.
    builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

    // Register API controller dependencies per request.
    builder.Register<ILogger>(c => new Logger()).InstancePerApiRequest();

    var container = builder.Build();

    // Set the dependency resolver implementation.
    var resolver = new AutofacWebApiDependencyResolver(container);
    configuration.ServiceResolver.SetResolver(resolver);
}

In the case of self hosting your bootstrapping code would look like this instead:

var configuration = new HttpSelfHostConfiguration("http://localhost:8080");

configuration.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new {id = RouteParameter.Optional}
    );

var builder = new ContainerBuilder();

// Configure the container with the integration implementations.
builder.ConfigureWebApi(configuration);

// Register API controllers using assembly scanning.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

// Register API controller dependencies per request.
builder.Register<ILogger>(c => new Logger()).InstancePerApiRequest();

var container = builder.Build();

// Set the dependency resolver implementation.
var resolver = new AutofacWebApiDependencyResolver(container);
configuration.ServiceResolver.SetResolver(resolver);

// Open the HTTP server and listen for requests.
using (var server = new HttpSelfHostServer(configuration))
{
    server.OpenAsync().Wait();

    Console.WriteLine("Hosting at http://localhost:8080/{controller}");
    Console.ReadLine();
}

First we are keeping a hold of the HttpConfiguration instance so that it can be provided to the ConfigureWebApi extension method on the ContainerBuilder. This is a HttpConfiguration instance when hosting in ASP.NET and a HttpSelfHostConfiguration instance when self hosting.

Next the RegisterApiControllers extension method on the ContainerBuilder is used to perform assembly scanning, looking for types that derive from IHttpController and have names with a suffix of “Controller”. This is very similar to how the MVC integration registers controllers using assembly scanning.

The InstancePerApiRequest method applied to the ILogger registration will cause it to be resolved once per API controller invocation. After the call completes it will be disposed automatically along with the API controller instance.

To avoid naming conflicts with the MVC integration the IDependencyResolver implementation has been named AutofacWebApiDependencyResolver. You provide it with the constructed container instance and then set it as the service resolver through the SetResolver method on the ServiceResolver property of the HttpConfiguration instance.

You will notice that the steps required to configure the integration are the same for both hosting scenarios. The only real difference is that the type of the HttpConfiguration instance changes depending on the hosting mode.

To register a service for lifetime scoping with both MVC controllers and Web API controllers you can apply both the InstancePerHttpRequest and InstancePerApiRequest lifetime scopes to the registration:

// Register MVC controller and API controller dependencies per request.
builder.Register(c => new Logger()).As<ILogger>()
    .InstancePerHttpRequest()
    .InstancePerApiRequest();

Implementation Details

Because of the two different hosting mechanisms a new way to manage lifetime scopes needed to found. The approach in the MVC and WCF integrations are completely different and I didn’t want both ways to be present in the Web API integration. The IHttpControllerFactory interface provided the required abstraction, though not in a perfect way.

public interface IHttpControllerFactory
{
    // Methods
    IHttpController CreateController(HttpControllerContext controllerContext, string controllerName);
    void ReleaseController(IHttpController controller);
}

This service is resolved from the dependency resolver if present, and is called by the HttpControllerDispatcher regardless of the hosting mode. The DefaultHttpControllerFactory that ships out-of-the-box handles a number of duties such as building and caching the HttpControllerDescriptor, along with various bits of exception handling. Implementing all of that did not sound like fun so I made the AutofacControllerFactory derive from the default implementation.

public class AutofacControllerFactory : DefaultHttpControllerFactory
{
    readonly ILifetimeScope _container;
    readonly ConcurrentDictionary<IHttpController, ILifetimeScope> _controllers = new ConcurrentDictionary<IHttpController, ILifetimeScope>();

    internal static readonly string ApiRequestTag = "AutofacWebRequest";

    public AutofacControllerFactory(HttpConfiguration configuration, ILifetimeScope container) : base(configuration)
    {
        if (container == null) throw new ArgumentNullException("container");
        _container = container;
    }

    public override IHttpController CreateController(HttpControllerContext controllerContext, string controllerName)
    {
        var lifetimeScope = _container.BeginLifetimeScope(ApiRequestTag);
        controllerContext.Request.Properties.Add(ApiRequestTag, lifetimeScope);

        try
        {
            var controller = base.CreateController(controllerContext, controllerName);
            if (controller != null)
                _controllers.TryAdd(controller, lifetimeScope);

            return controller;
        }
        catch (Exception)
        {
            lifetimeScope.Dispose();
            throw;
        }
    }

    public override void ReleaseController(IHttpController controller)
    {
        ILifetimeScope lifetimeScope;
        if (controller != null && _controllers.TryRemove(controller, out lifetimeScope))
            if (lifetimeScope != null)
                lifetimeScope.Dispose();
    }
}

The AutofacControllerFactory has the current ILifetimeScope injected which happens to be the root lifetime scope at the point when it is created. This will be used to create nested lifetime scopes for each controller request. When Web API asks for a controller using the CreateController method a new lifetime scope is created based on a tag that is used during the container registration process. The same tag is used in the MVC 4 integration to allow services to be registered per MVC controller and per Web API controller. The new lifetime scope is then poked into a property on the HttpRequestMessage that is accessible from the provided HttpControllerContext. It may seem a little strange at first but the creation of the controller is being delegated to the base class, which in turn looks for an IHttpControllerActivator instance in the dependency resolver, and if located will use that to create the actual controller instance. As you have properly guessed already there is an Autofac implementation of the IHttpControllerActivator that will retrieve the lifetime scope from that property and use it to create the controller instance and its dependencies in the correct lifetime scope.

public class AutofacControllerActivator : IHttpControllerActivator
{
    public IHttpController Create(HttpControllerContext controllerContext, Type controllerType)
    {
        var requestProperties = controllerContext.Request.Properties;

        if (!requestProperties.ContainsKey(AutofacControllerFactory.ApiRequestTag))
            throw GetInvalidOperationException();

        ILifetimeScope lifetimeScope = requestProperties[AutofacControllerFactory.ApiRequestTag] as ILifetimeScope;
        if (lifetimeScope == null)
            throw GetInvalidOperationException();

        return lifetimeScope.ResolveOptional(controllerType) as IHttpController;
    }

    internal static InvalidOperationException GetInvalidOperationException()
    {
        return new InvalidOperationException(
            string.Format(AutofacControllerActivatorResources.LifetimeScopeMissing,
                typeof(ILifetimeScope).FullName, typeof(HttpRequestMessage).FullName, typeof(AutofacControllerFactory).FullName));
    }
}

AutofacControllerActivator expects that if it is present in the dependency resolver, then the Autofac controller factory should be as well, and should have put the lifetime scope into the property on the HttpRequestMessage. It also expects that if the property is present that it should contain an ILifetimeScope that it can use to attempt to resolve the controller. If the controller is not found in the lifetime scope a null reference is returned and that will cause an exception to be thrown in the DefaultHttpControllerFactory when the null is assigned to the Controller property of the HttpControllerContext. Looking at the code in the current implementation of the HttpControllerDispatcher it seems that it actually expects a null being returned from the factory as a possibility even though it seems like this cannot happen.

IHttpController httpController = this._controllerFactory.CreateController(controllerContext, str);
if (httpController == null)
{
    return TaskHelpers.FromResult<HttpResponseMessage>(request.CreateResponse(HttpStatusCode.NotFound));
}

Regardless, back in the AutofacControllerFactory any exceptions are caught to ensure that the lifetime scope can be disposed immediately before re-throwing the exception. The lifetime scope is placed into a ConcurrentDictionary using the controller instance as the key, so that it can be disposed when the ReleaseController method is called after the request is complete. Unfortunately, nothing else is passed to this method so the dictionary was required to tie the controller being released back to a lifetime scope. It would be great if more context was provided between these calls so that lifetime scope could be more easily managed.

The IDependencyResolver implementation is very basic and has been named AutofacWebApiDependencyResolver to avoid naming conflicts with the existing MVC implementation. In the Web API integration it works with the root container most of the time instead of looking for a current lifetime scope. Taking the approach of always looking for an ambient lifetime scope provided to be too difficult with the dual hosting model. I don’t think this will be a problem as outside of the lifetime scope for the API controller, it appears that most services are expected to be singleton or new instances on each call.

public class AutofacWebApiDependencyResolver : IDependencyResolver
{
    readonly ILifetimeScope _container;

    public AutofacWebApiDependencyResolver(ILifetimeScope container)
    {
        if (container == null) throw new ArgumentNullException("container");
        _container = container;
    }

    public object GetService(Type serviceType)
    {
        return _container.ResolveOptional(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        var enumerableServiceType = typeof(IEnumerable<>).MakeGenericType(serviceType);
        var instance = _container.Resolve(enumerableServiceType);
        return (IEnumerable<object>)instance;
    }
}

The registration extensions are also straight forward. ConfigureWebApi registers the HttpConfiguration instance making available to other services, and ensures that the Autofac controller factory and activator are registered too. Obviously, not much is going to happen if this method is not called before building your container.

public static void ConfigureWebApi(this ContainerBuilder builder, HttpConfiguration configuration)
{
    builder.RegisterInstance(configuration);
    builder.Register<IHttpControllerActivator>(c => new AutofacControllerActivator())
        .SingleInstance();
    builder.Register<IHttpControllerFactory>(c => new AutofacControllerFactory(c.Resolve<HttpConfiguration>(), c.Resolve<ILifetimeScope>()))
        .SingleInstance();
}

Scanning for controllers is implemented similar to the MVC integration except we are looking for IHttpController derived types instead.

public static IRegistrationBuilder<object, ScanningActivatorData, DynamicRegistrationStyle>
    RegisterApiControllers(this ContainerBuilder builder, params Assembly[] controllerAssemblies)
{
    return builder.RegisterAssemblyTypes(controllerAssemblies)
        .Where(t => typeof(IHttpController).IsAssignableFrom(t) && t.Name.EndsWith("Controller"));
}

Finally, and once again similar to the MVC InstancePerHttpRequest method, the InstancePerApiRequest method applies the predetermined tag to the registration so that it can be resolved within the API controller lifetime scope.

public static IRegistrationBuilder<TLimit, TActivatorData, TStyle>
    InstancePerApiRequest<TLimit, TActivatorData, TStyle>(
        this IRegistrationBuilder<TLimit, TActivatorData, TStyle> registration)
{
    if (registration == null) throw new ArgumentNullException("registration");

    return registration.InstancePerMatchingLifetimeScope(AutofacControllerFactory.ApiRequestTag);
}

That pretty much covers it. Please download the package and report any bugs on the issue tracker or if you need help post your questions on Stack Overflow using the “autofac” tag. It will be interesting to see how much things change between this Beta and the final RTW. Happing API building!

Tags:

Autofac

Autofac ASP.NET MVC 4 (Beta) Integration

by Alex Meyer-Gleaves 8 March 2012 - 8:20 AM

Following the release of Autofac 2.6.1, the Autofac MVC 4 Beta integration is now ready for downloading via NuGet. I will look into what additional features might be possible later, but the immediate priority was to make something available ensuring people could starting enjoying Autofac with MVC 4 Beta. This work is currently being done in a branch and will be merged back into the mainline once the final RTW of MVC 4 is made available.

Install-Package Autofac.Mvc4

There are no breaking changes in the API between this and the MVC 3 version of the integration so the upgrade should be fairly painless. Detailed instructions for upgrading your actual MVC 3 project can be found in the MVC 4 release notes.

Please download the package and report any bugs on the issue tracker or if you need help post your questions on Stack Overflow using the “autofac” tag. The current MVC 3 documentation on the wiki still applies and can help you get up and running if your new to the integration.

A minor change was made in the internals to allow the lifetime scope applied to a registration to be shared between MVC and the Web API (which you have no doubt now deduced is on the way too).

// Register MVC controller and API controller dependencies per request.
builder.Register(c => new Logger()).As<ILogger>()
    .InstancePerHttpRequest()
    .InstancePerApiRequest();

Technically both extension methods use the same tag for the nested lifetime scope so only one is really needed, but I like adding both because makes it obvious that the service will be scoped to the controller, regardless of it being of the MVC or Web API variety. I don’t think there is too much more to add other than to watch out for the Web API integration which will probably be available by the time you read this.

Tags:

Autofac

FilterAttribute Property Injection in Autofac MVC 3 Integration

by Alex Meyer-Gleaves 24 March 2011 - 3:56 AM

The current mechanism for performing property injection on FilterAttribute instances via the ExtensibleActionInvoker had to be removed recently due to a rather nasty bug. These are the notes that Nick provided outlining the problem he discovered (possibly with the help of the exciting new Whitebox profiler).

Because the filters passed from the base action invoker also include the controller, property injection happens on the controller itself several times as the filters are processed.

The filter attributes also included in the collection may also be singletons cached by MVC, and so it is quite likely that dependencies may be overwritten with those from a concurrently executing request.

In all this behaviour is probably too risky to reliably support.

Removed property injection routine. (Breaking change.)

I have replaced the old mechanism using an approach that leverages the improved dependency injection support added to MVC 3 (this will be in the next release). To make use of property injection for your filter attributes all you will need to do is call the RegisterFilterProvider method on the ContainerBuilder before building your container and providing it to the AutofacDependencyResolver.

ContainerBuilder builder = new ContainerBuilder();

builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.Register(c => new Logger()).As<ILogger>().InstancePerHttpRequest();
builder.RegisterFilterProvider();

IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

Then you can add properties to your filter attributes and any matching dependencies that are registered in the container will be injected into the properties. For example, the action filter below will have the ILogger instance that was registered above injected. Note that the attribute itself does not need to be registered in the container.

public class CustomActionFilter : ActionFilterAttribute
{
    public ILogger Logger { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Logger.Log("OnActionExecuting");
    }
}

The same simple approach applies to the other filter attribute types such as authorization attributes.

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    public ILogger Logger { get; set; }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        Logger.Log("AuthorizeCore");
        return true;
    }
}

After applying the attributes to your actions as required your work is done.

[CustomActionFilter]
[CustomAuthorizeAttribute]
public ActionResult Index()
{
    // ...
}

To make this work I added a custom FilterAttributeFilterProvider implementation. The custom filter provider delegates the job of collecting the filters to the base class. Once the filters have been retrieved by the base class, the ILifetimeScope for the current HTTP request is retrieved and used to perform property injection on the filters. The false passed to the base FilterAttributeProvider constructor sets the cacheAttributeInstances parameter to ensure that attribute instances are not cached. Allowing the attribute instances to be cached would result in race conditions and other unexpected behaviour.

/// <summary>
/// Defines a filter provider for filter attributes that performs property injection.
/// </summary>
public class AutofacFilterAttributeFilterProvider : FilterAttributeFilterProvider
{
    /// <summary>
    /// Initializes a new instance of the <see cref="AutofacFilterAttributeFilterProvider"/> class.
    /// </summary>
    /// <remarks>
    /// The <c>false</c> constructor parameter passed to base here ensures that attribute instances are not cached.
    /// </remarks>
    public AutofacFilterAttributeFilterProvider() : base(false)
    {
    }

    /// <summary>
    /// Aggregates the filters from all of the filter providers into one collection.
    /// </summary>
    /// <param name="controllerContext">The controller context.</param>
    /// <param name="actionDescriptor">The action descriptor.</param>
    /// <returns>
    /// The collection filters from all of the filter providers with properties injected.
    /// </returns>
    public override IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        var filters = base.GetFilters(controllerContext, actionDescriptor).ToArray();
        var lifetimeScope = AutofacDependencyResolver.Current.RequestLifetimeScope;

        if (lifetimeScope != null)
            foreach (var filter in filters)
                lifetimeScope.InjectProperties(filter.Instance);

        return filters;
    }
}

The RegisterFilterProvider method has been added to the ContainerBuilder using an extension method. This method will register the AutofacFilterAttributeFilterProvider using the IFilterProvider interface that MVC uses when asking the dependency resolver for filter providers. Following the instructions outlined in Brad Wilson’s post on the subject of dependency injection and filters, I made sure that the default FilterAttributeFilterProvider instance is removed from the static collection of providers.

/// <summary>
/// Registers the <see cref="AutofacFilterAttributeFilterProvider"/>.
/// </summary>
/// <param name="builder">The container builder.</param>
public static void RegisterFilterProvider(this ContainerBuilder builder)
{
    if (builder == null) throw new ArgumentNullException("builder");

    foreach (var provider in FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().ToArray())
        FilterProviders.Providers.Remove(provider);

    builder.RegisterType<AutofacFilterAttributeFilterProvider>()
        .As<IFilterProvider>()
        .SingleInstance();
}

If you were using the old mechanism you will have breaking changes to contend with, but as you can see it should be easy to get back on track again.

Tags: ,

Autofac | Web Development

View Page Injection in Autofac ASP.NET MVC 3 Integration

by Alex Meyer-Gleaves 28 December 2010 - 11:31 PM

The increased support for dependency injection in ASP.NET MVC 3 includes the ability to have your view pages created by your favourite container.

Historically, these classes have not had access to dependency injection/service location functionality, because their creation was buried deep inside the implementation of the view engine. In MVC 3, we have updated the built-in view engines to attempt to create the view page classes via the service locator; if that fails, it will fall back to using Activator.CreateInstance, just like in previous versions of MVC.

Because the view pages are dynamically compiled at runtime a few restrictions have been imposed; you cannot use constructor injection and your view pages must inherit from a custom base class.

The problem is that your .aspx/.ascx/.cshtml/.vbhtml files are converted into classes at runtime by the ASP.NET Build Manager (in collaboration with build providers). When those classes are auto generated, they are auto generated only with a single parameterless constructor.

We looked at auto-generating constructors, but it turns out that we don't actually know enough about the base class when we're generating the code to actually do any reflection on it, so it's not really possible for us to look at the base class and determine which constructors it may or may not have.

Happy that these limitations are not going to pose any serious problems let’s move onto the Autofac integration. Time for yet another uninspiring example, but one that should be easy to follow and doesn’t require too much typing on my part. Imagine that we have a service that provides common company information such as a copyright that we need to display on all our view pages.

public interface ICompanyInformation
{
    string Copyright { get; }
}

There is of course an implementation of the service that returns the dynamic copyright information (you were warned about the example).

public class CompanyInformation : ICompanyInformation
{
    public string Copyright
    {
        get { return string.Format("Copywrong &copy; {0} ACME Corporation", DateTime.Now.Year); }
    }
}

In the application start event we build our container and register the service along with our controllers. We also add a registration source called ViewRegistrationSource.

ContainerBuilder builder = new ContainerBuilder();
builder.Register(c => new CompanyInformation()).As<ICompanyInformation>().InstancePerHttpRequest();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterSource(new ViewRegistrationSource());

IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

The registration source is where all the magic happens. A registration source allows you to create an adapter that will dynamically provide a registration for a service. We know that MVC will ask the container for an instance of the view page before it attempts to create it itself, so we can use the registration source to make sure that the container always knows how to provide such an instance. Below is the implementation of the registration source for those that are interested in the details.

public class ViewRegistrationSource : IRegistrationSource
{
    public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
    {
        var typedService = service as IServiceWithType;

        if (typedService != null && IsSupportedView(typedService.ServiceType))
            yield return RegistrationBuilder.ForType(typedService.ServiceType)
                .PropertiesAutowired()
                .InstancePerHttpRequest()
                .CreateRegistration();
    }

    public bool IsAdapterForIndividualComponents
    {
        get { return false; }
    }

    static bool IsSupportedView(Type serviceType)
    {
        return serviceType.IsAssignableTo<WebViewPage>() 
            || serviceType.IsAssignableTo<ViewPage>()
            || serviceType.IsAssignableTo<ViewMasterPage>()
            || serviceType.IsAssignableTo<ViewUserControl>();
    }
}

If the requested service inherits from one of the supported view base classes, the RegistrationBuilder.ForType helper is used to build the registration. The registration also makes sure that property injection is performed and that the lifetime is scoped to the HTTP request. The Razor view base class WebViewPage is supported, along with the WebForms base classes ViewPage, ViewMasterPage and ViewUserControl.

To get properties on the view page that can be injected by the container, you need to slot your own base class into the inheritance hierarchy. This is as simple as creating an abstract class that derives from WebViewPage or WebViewPage<T> when using the Razor view engine.

public abstract class CustomViewPage : WebViewPage
{
    public ICompanyInformation CompanyInformation { get; set; }
}

If you are using the WebForms view engine in your MVC project you would derive from the ViewPage or ViewPage<T> class instead.

public abstract class CustomViewPage : ViewPage
{
    public ICompanyInformation CompanyInformation { get; set; }
}

The last thing you need to do is ensure that your actual view page inherits from your custom base class. This can be achieved using the @inherits directive inside your .cshtml file for the Razor view engine.

@inherits Example.Views.Shared.CustomViewPage

@{
    ViewBag.Title = "Home Page";
}

<h2>@ViewBag.Message</h2>
<p>
    This is the page content.
</p>
<p>
    @CompanyInformation.Copyright
</p>

When using the WebForms view engine you set the Inherits attribute on the @ Page directive inside you .aspx file instead.

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="Example.Views.Shared.CustomViewPage"%>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Home Page
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2><%: ViewBag.Message %></h2>
    <p>
        This is the page content.
    </p>
    <p>
        <%= CompanyInformation.Copyright %>
    </p>
</asp:Content>

Making your custom base class inherit from the generic WebViewPage<T> or ViewPage<T> class allows you to provide your strongly typed model as the generic type parameter. You can of course choose to leave the generic type parameter in your base class open making it more reusable.

public abstract class CustomViewPage<T> : WebViewPage<T>
{
    public ICompanyInformation CompanyInformation { get; set; }
}

You simply provide the model type as the closing generic parameter in the type declared in the @inherits or Inherits attribute of the page.

@inherits Example.Views.Shared.CustomViewPage<Example.Models.CustomModel> 

Taking advantage of view page injection is a very simple matter. No doubt you will have much more creative uses for this than the simplified example shown here.

Tags: ,

Autofac | Web Development

Model Binder Injection in Autofac ASP.NET MVC 3 Integration

by Alex Meyer-Gleaves 7 December 2010 - 11:30 PM

The Autofac MVC integration supported model binder injection in the MVC 2 version, but improvements in the dependency injection support offered by MVC 3 has allowed the implementation to be made cleaner. ASP.NET MVC 3 introduces the IModelBinderProvider interface that allows the implementer to determine what model binder should be used for a particular type.

Developers who implement this interface can optionally return an implementation of IModelBinder for a given type (they should return null if they cannot create a binder for the given type).

Let’s start by looking at how the model binder injection is configured in the MVC integration. You first create a class that implements IModelBinder like you would when creating any other model binder in MVC. Next you apply the ModelBinderType attribute provided as part of the integration to indicate what types the model binder supports binding. The simple example below declares that the model binder supports binding for string types.

[ModelBinderType(typeof(string))]
public class StringBinder : IModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // Do implementation here.
    }
}

You then use the RegisterModelBinders extension method on the ContainerBuilder to register all the IModelBinder types that are present in one or more assemblies.

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterModelBinders(Assembly.GetExecutingAssembly());

The interesting part about the implementation of the assembly scanning is that it finds the types the model binder supports through the ModelBinderType attributes and then adds this information as metadata to the registration.

public static IRegistrationBuilder<object, ScanningActivatorData, DynamicRegistrationStyle>
    RegisterModelBinders(this ContainerBuilder builder, params Assembly[] modelBinderAssemblies)
{
    return builder.RegisterAssemblyTypes(modelBinderAssemblies)
        .Where(type => typeof(IModelBinder).IsAssignableFrom(type))
        .As<IModelBinder>()
        .InstancePerHttpRequest()
        .WithMetadata(AutofacModelBinderProvider.MetadataKey, type => 
            (from ModelBinderTypeAttribute attribute in type.GetCustomAttributes(typeof(ModelBinderTypeAttribute), true)
             from targetType in attribute.TargetTypes
            select targetType).ToList());
}

You must also remember to register the AutofacModelBinderProvider using the RegisterModelBinderProvider extension method. This is Autofac's implementation of the new IModelBinderProvider interface.

builder.RegisterModelBinderProvider();

The constructor of the AutofacModelBinderProvider requests that an IEnumerable<Meta<Lazy<IModelBinder>>> be provided. When the GetBinder method is called through the IModelBinderProvider interface, the list of Meta<T> about the components is queried to locate any potential matches based on the types stored in the metadata. The Lazy<T> part of dependency makes sure that we do not actually create an instance of the IModelBinder until it is actually needed.

public IModelBinder GetBinder(Type modelType)
{
    Meta<Lazy<IModelBinder>> modelBinder = _modelBinders
        .FirstOrDefault(binder => ((List<Type>)binder.Metadata[MetadataKey]).Contains(modelType));
    return (modelBinder != null) ? modelBinder.Value.Value : null;
}

This dynamic approach to handling model binder injection removes the need for a special wrapper around each IModelBinder component, and avoids having to register this wrapper directly into the static ModelBinders.Binders dictionary.

Tags:

Autofac | Web Development

ASP.NET MVC 3 Beta integration for Autofac

by Alex Meyer-Gleaves 4 November 2010 - 2:38 AM

I have just checked into trunk a first pass at the ASP.NET MVC 3 Beta integration for Autofac. In hope of simplifying the requirements for those getting started with the integration I wanted to prevent the need to:

The code below is an example of all you would need to put into the application start event to get up and running.

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.Register(c => new Logger()).As<ILogger>().InstancePerHttpRequest();

IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

The core piece of the integration is the AutofacDependencyResolver. This is an implementation of the IDependencyResolver interface that Brad Wilson outlines in his blog post series on ASP.NET MVC 3 Service Location. The interface requires you to implement two simple methods: GetService and GetServices. When no service is found GetService should return null, and GetServices should return an empty IEnumerable<object>. The implementation of these methods ends up being straight forward (ignoring for now the code related to managing the CurrentLifetimeScope).

public object GetService(Type serviceType)
{
    return CurrentLifetimeScope.IsRegistered(serviceType) ? CurrentLifetimeScope.Resolve(serviceType) : null;
}

public IEnumerable<object> GetServices(Type serviceType)
{
    Type enumerableServiceType = typeof(IEnumerable<>).MakeGenericType(serviceType);
    object instance = CurrentLifetimeScope.Resolve(enumerableServiceType);
    return ((IEnumerable)instance).Cast<object>();
}

When MVC needs to create a controller it will ask the DependencyResolver for an instance. The AutofacDependencyResolver returns the controllers that are registered in the container it was provided. These are usually registered using the RegisterControllers method on the ContainerBuilder as shown in the first code sample. There is no longer a need to create a class that derives from the DefaultControllerFactory for the sole purpose of returning controller instances. This means the AutofacControllerFactory is no longer required and has been removed.

The Autofac MVC integration has always supported the concept of a HTTP request lifetime scope. This means that the lifetime of a service can be scoped to the current HTTP request. The ILogger service registration in the sample code above uses the InstancePerHttpRequest method to indicate that the same instance of the logger service should be used for all dependency resolutions that occur during the current HTTP request. To make sure that the nested lifetime scope that Autofac creates for each request is disposed, it needs to be notified when the request has ended.

The only reliable way to do this is to create a HTTP module that subscribes to the EndRequest event of the HttpApplication. To register a HTTP module you need to add an entry to the web configuration file, which is something that I was hoping to avoid. Rick Strahl outlines one way of achieving programmatic registration of a module in his Dynamically hooking up HttpModules post, but for the integration this would require the user to manually add the code to their HttpApplication instance (by default called MvcApplication).

It turns out that there is in fact another way to programmatically register a module. The Microsoft.Web.Infrastructure.dll assembly that ships with the ASP.NET Web Pages installer (AspNetWebPages.msi) contains a rather helpful class called DynamicModuleUtility. It has a single method called RegisterModule that accepts a Type for the module to register. You can only call this helper from a method that is marked as pre application start code as defined by the PreApplicationStartMethodAttribute applied to an assembly. The same trick is used in System.Web.Pages.dll to register the new WebPageHttpModule. Phil Haack has a blog post that talks about the PreApplicationStartMethodAttribute and some other interesting new ASP.NET 4 features in greater detail if you are keen to know more. You need to install ASP.NET Web Pages before installing ASP.NET MVC 3 so we know the assembly with this helpful little gem will be available.

In the Autofac integration we first needed to add the assembly attribute.

[assembly: PreApplicationStartMethod(typeof(PreApplicationStartCode), "Start")]

This points to a static class that contains a single static method called Start. Inside this method we call the DynamicModuleUtility to register the RequestLifetimeModule that will informs us when the HTTP request has ended. There is no need to ever call this class directly but unfortunately, it and the method must be public. That is why we have the EditorBrowsable attribute being applied in order to hide the class from the editor. Not really that much work to save a user from having to dive into the web configuration file.

[EditorBrowsable(EditorBrowsableState.Never)]
public static class PreApplicationStartCode
{
    private static bool _startWasCalled;

    public static void Start()
    {
        if (_startWasCalled) return;

        _startWasCalled = true;
        DynamicModuleUtility.RegisterModule(typeof(RequestLifetimeModule));
    }
}

There is a new interface in the MVC 3 integration called ILifetimeScopeProvider. The HTTP module RequestLifetimeModule shown above actually implements this interface and is the default implementation used by the AutofacDependencyResolver. You can see from the AutofacDependencyResolver code shown at the start of the post that the resolutions are happening from the CurrentLifetimeScope property.

internal ILifetimeScope CurrentLifetimeScope
{
    get
    {
        if (_lifetimeScopeProvider == null)
            _lifetimeScopeProvider = GetRequestLifetimeModule();
        return _lifetimeScopeProvider.GetLifetimeScope(_container, _configurationAction);
    }
}

You can add your own ILifetimeScopeProvider implementation to the container that is passed to the AutofacDependencyResolver if you want to replace the HTTP request based lifetime behaviour. The AutofacDependencyResolver will attempt to retrieve it from the container during its constructor. Because the RequestLifetimeModule is the default ILifetimeScopeProvider and an instance was already created by ASP.NET when the module was initialised, we can go and grab that from the HttpModuleCollection of the current HttpApplication.

static ILifetimeScopeProvider GetRequestLifetimeModule()
{
    HttpModuleCollection httpModules = HttpContext.Current.ApplicationInstance.Modules;
    for (int index = 0; index < httpModules.Count; index++)
    {
        if (httpModules[index] is RequestLifetimeModule)
            return (RequestLifetimeModule)httpModules[index];
    }
    throw new InvalidOperationException(string.Format(
        AutofacDependencyResolverResources.HttpModuleNotLoaded, typeof(RequestLifetimeModule)));
}

None of the model binding code has been moved into the new integration yet. I am hoping that this can be refactored to use the new IModelBinderProvider interface. This is only a first pass based on a new approach so it is likely that some of this will change. I have certainly found the exercise interesting enough that I thought it was worth sharing the start of the journey.

Tags: ,

Autofac | Web Development

Introducing Action Injection with Autofac ASP.NET MVC Integration

by Alex Meyer-Gleaves 16 May 2010 - 2:33 AM

There are currently two main approaches to performing dependency injection, Constructor Injection and Setter Injection. The more popular of the two approaches is Constructor Injection. The dependencies that a type has are made obvious because they must be supplied in order to construct an instance. This also makes it easier for you to ensure that a newly instantiated object is in a valid state. When working with a type the constructor is usually the first thing that you come into contact with.

With Setter Injection, also known as Property Injection, it is much more difficult to tell what the dependencies are when looking at the type from the outside. Setter Injection is most useful when you have no control over the instantiation of the type that requires the dependencies to be injected. This is a common scenario for ASP.NET WebForms where the activation of a Page instance is performed by the runtime. You do not have an opportunity to take over the activation process, and the first chance you have to perform dependency injection is when you are provided with an existing instance of Page. In this case you have no choice but to inject the dependencies into the type via its properties.

ASP.NET MVC has many extensibility points and is very flexible. It provides you with the opportunity to take over the creation of your Controller instances by creating your own factory that implements IControllerFactory, or more commonly by deriving from the DefaultControllerFactory and overriding the GetControllerInstance method. This makes it possible for your controllers to take advantage of Constructor Injection, and is exactly what the Autofac ASP.NET MVC Integration does. When it comes to unit testing your controller classes, it becomes very easy to see what dependencies it has, and to provide mock implementations for those dependencies.

An issue that is often raised in regards to Constructor Injection is what some people like to call Constructor Bloat. This may indicate that you are not following the Single Responsibility Principle and that some refactoring may be in order. The number of constructor parameters that would be considered too many would no doubt vary depending on who you ask. In the case of ASP.NET MVC controllers the number of constructor dependencies is more likely to be higher than for other classes. The level of responsibility for a controller is usual greater than what you would expect for an ordinary internal component. This is the result of mapping an external view of the application (URL based) onto an internal representation (controller based).

It turns out that both Nicholas Blumhardt and I found ourselves shifting some of these dependencies out of the controller’s constructor and into the action methods that actually require them. We were both fairly surprised to find out that the other had independently been doing exactly the same thing, and at this point discussed if there was something wrong with the approach because it seemed that no one else was doing it. Surely all good ideas have already been done so this one must be bad. I personally feel that having dependencies injected into your action method should not feel like a foreign concept because that is exactly what MVC is already doing for you with your existing parameters.

For lack of any official term that I am aware of, Action Injection is what I am calling this particular approach to dependency injection in ASP.NET MVC. The more I play around with this approach the more I like it. Your constructor is provided the dependencies that are shared by all actions in your controller, and each individual action can request any additional dependencies that it needs. Now when writing unit tests for your actions there is no need to provide mock implementations for dependencies that your action will not be interacting with. The end result is less mocks in your unit tests and a clear indication of the action’s actual dependencies.

Nick and I have decided to test out the idea of Action Injection in the Autofac ASP.NET MVC Integration. The changes are only in the source code at the moment and have not yet been included in a release. I mentioned earlier that MVC is very extensible and the process for invoking your action methods is no different. It is possible to replace the default behaviour by creating your own IActionInvoker. The easiest way to do this is by deriving from the AsyncControllerActionInvoker class and overriding the appropriate methods. A controller can be requested to use your custom action invoker by assigning an instance to the controller's ActionInvoker property. The current source includes a registration extension that allows you to register an IActionInvoker instance that will be assigned to a controller as it is activated. There is a default IActionInvoker implementation called ExtensibleActionInvoker that allows dependencies to be injected into your action methods. It can also do Setter Injection on your filters but that is a topic for another post. As the name suggests, you can extend this class and add any additional behaviour that you require. Registering controllers in the HttpApplication start would look something like this.

ContainerBuilder builder = new ContainerBuilder();

builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();
builder.RegisterControllers(Assembly.GetExecutingAssembly()).InjectActionInvoker();

// Register other services.

IContainer container = builder.Build();
_containerProvider = new ContainerProvider(container);

ControllerBuilder.Current.SetControllerFactory(new AutofacControllerFactory(_containerProvider));

I will not go into further detail on the implementation at this point because it may be tweaked a little before being released. Instead, let us look at an example of how we could make our action dependencies clearer using Action Injection. The NotifyController class below has action methods that send the current user a message using different delivery methods.

public class NotifyController
{
    public NotifyController(ILogger logger, 
        IEmailNotifier emailNotifier, 
        ISmsNotifier smsNotifier, 
        IMessengerNotifier messengerNotifier)
    {
        // Implementation.
    }
    
    public ActionResult Email(string message)
    {
        // Implementation.
    }
    
    public ActionResult Sms(string message)
    {
        // Implementation.
    }

    public ActionResult Messenger(string message)
    {
        // Implementation.
    }
}

There are three action methods on this controller and four dependencies that must be provided through the constructor. To unit test any of the action methods all four of the dependencies will need to be mocked. In this controller the ILogger instance is required by all action methods, but the remaining notifier dependencies are each required only by one action method. The controller could be refactored so that it takes the one ILogger dependency through its constructor, and each action could take its particular notifier dependency through a method parameter. Here is an example of how the refactored code would look.

public class NotifyController
{
    public NotifyController(ILogger logger)
    {
        // Implementation.
    }
    
    public ActionResult Email(string message, IEmailNotifier emailNotifier)
    {
        // Implementation.
    }
    
    public ActionResult Sms(string message, ISmsNotifier smsNotifier)
    {
        // Implementation.
    }

    public ActionResult Messenger(string message, IMessengerNotifier messengerNotifier)
    {
        // Implementation.
    }
}

Now when testing the action methods we only ever need to provide two mock services. There is no need to provide additional mock services that will never be used. Assuming we only had one unit test per action and setup our mocks inside each unit test, we would have halved the number of mocks required, taking the total from twelve down to six. That certainly seems like an improvement to me.

I would be interested to know what you think about this idea. Is it totally crazy or could there be something to it? Maybe you too have already been doing this and could share how it has been working out for you.

Tags: ,

Autofac | Web Development

Making Self-Hosting with Autofac WCF Integration easier

by Alex Meyer-Gleaves 16 May 2010 - 1:48 AM

Thinking about the sample I recently posted for shelf-hosting WCF Services with the Autofac WCF Integration, I decided that the boilerplate code for configuring the Service Behavior could be moved into an extension method on the ServiceHost instead. I have checked in some code that will extend ServiceHostBase with a new method called AddDependencyInjectionBehavior. There are two overloads of the method, one that takes a generic argument for the service contract type, and another that allows you to provide a Type for the service contract in case you are configuring your WCF Services in some sort of latebound manner. Both overloads of the method require an IContainer instance.

host.AddDependencyInjectionBehavior<IEchoService>(container);
host.AddDependencyInjectionBehavior(typeof(IEchoService), container);

As you can see from the updated sample below, the extension method makes the code considerably more concise, and will save you from having to write your own helper method that can be reused with your different WCF Services.

ContainerBuilder builder = new ContainerBuilder();
builder.Register(c => new Logger()).As<ILogger>();
builder.Register(c => new EchoService(c.Resolve<ILogger>())).As<IEchoService>();

using (IContainer container = builder.Build())
{
    Uri address = new Uri("http://localhost:8080/EchoService");
    ServiceHost host = new ServiceHost(typeof(EchoService), address);

    host.AddServiceEndpoint(typeof(IEchoService), new BasicHttpBinding(), string.Empty);

    host.AddDependencyInjectionBehavior<IEchoService>(container);

    host.Description.Behaviors.Add(new ServiceMetadataBehavior {HttpGetEnabled = true, HttpGetUrl = address});
    host.Open();
    
    Console.WriteLine("The host has been opened.");
    Console.ReadLine();

    host.Close();
    Environment.Exit(0);
}

The extension method will be available in the next release of Autofac. If you want to try it out without grabbing the latest Autofac source, the code below should give you a feel for how it works. You do not need to provide the service implementation type to the extension method because it can be retrieved from the ServiceHost instance. The Type instance that you provide in the ServiceHost constructor surfaces as the ServiceHost.Description.ServiceType property and can be used directly in the extension method.

public static class ServiceHostExtensions
{
    public static void AddDependencyInjectionBehavior<T>(this ServiceHostBase serviceHost, IContainer container)
    {
        AddDependencyInjectionBehavior(serviceHost, typeof(T), container);
    }

    public static void AddDependencyInjectionBehavior(this ServiceHostBase serviceHost, Type contractType, IContainer container)
    {
        IComponentRegistration registration;
        if (!container.ComponentRegistry.TryGetRegistration(new TypedService(contractType), out registration))
        {
            string message = string.Format("The service contract type '{0}' has not been registered in the container.", contractType.FullName);
            throw new ArgumentException(message);
        }

        AutofacDependencyInjectionServiceBehavior behavior = new AutofacDependencyInjectionServiceBehavior(
            container, serviceHost.Description.ServiceType, registration);
        serviceHost.Description.Behaviors.Add(behavior);
    }
}

Nothing fancy here but that should make self-hosting a little easier.

Tags: ,

Autofac | Web Services

Self-Hosting WCF Services with the Autofac WCF Integration

by Alex Meyer-Gleaves 7 May 2010 - 12:14 AM

A question came up recently in the Autofac group about how to use the WCF Integration when self-hosting WCF Services. This post provides a quick demonstration of how to handle the self-hosting scenario and should be enough to get you started. The example is a rather unimaginative web service that echoes back a message.

First declare the interface and implementation for a logger that the WCF Service will take as a dependency in its constructor. This is a simple logger that will log the message sent to the WCF Service out to the console.

public interface ILogger
{
    void Write(string message);
}

public class Logger : ILogger
{
    public void Write(string message)
    {
        Console.WriteLine(message);
    }
}

Next you need to define the contract and implementation for the WCF Service. Nothing interesting here other than our dependency being requested through the constructor of the WCF Service implementation.

[ServiceContract]
public interface IEchoService
{
    [OperationContract]
    string Echo(string message);
}

public class EchoService : IEchoService
{
    private readonly ILogger _logger;

    public EchoService(ILogger logger)
    {
        _logger = logger;
    }

    public string Echo(string message)
    {
        _logger.Write(message);
        return message;
    }
}

Now we can create a Console Application that will configure the container and host our WCF Service.

ContainerBuilder builder = new ContainerBuilder();
builder.Register(c => new Logger()).As<ILogger>();
builder.Register(c => new EchoService(c.Resolve<ILogger>())).As<IEchoService>();

using (IContainer container = builder.Build())
{
    Uri address = new Uri("http://localhost:8080/EchoService");
    ServiceHost host = new ServiceHost(typeof(EchoService), address);
    host.AddServiceEndpoint(typeof(IEchoService), new BasicHttpBinding(), string.Empty);

    IComponentRegistration registration;
    if (!container.ComponentRegistry.TryGetRegistration(new TypedService(typeof(IEchoService)), out registration))
    {
        Console.WriteLine("The service contract has not been registered in the container.");
        Console.ReadLine();
        Environment.Exit(-1);
    }

    host.Description.Behaviors.Add(new AutofacDependencyInjectionServiceBehavior(container, typeof(EchoService), registration));
    host.Description.Behaviors.Add(new ServiceMetadataBehavior {HttpGetEnabled = true, HttpGetUrl = address});
    host.Open();
    
    Console.WriteLine("The host has been opened.");
    Console.ReadLine();

    host.Close();
    Environment.Exit(0);
}

Here we have added an IServiceBehavior called AutofacDependencyInjectionServiceBehavior that will add a custom IInstanceProvider to the DispatchRuntime of each endpoint’s EndpointDispatcher. That is a bit of a mouth full but basically means that Autofac will use the WCF extensibility points to provide WCF Service instances that have their dependencies injected.

In this example the WCF Service is exposed on an endpoint that uses the BasicHttpBinding but you can use any type of endpoint that you like. I have added a ServiceMetadataBehavior in this example that exposes the WSDL for the WCF Service at http://localhost:8080/EchoService?wsdl. You can use this address to create a client proxy and send test messages that are hopefully more creative than my example.

Tags: ,

Autofac | Web Services

Autofac 2.0 Podcast

by Alex Meyer-Gleaves 6 April 2010 - 12:47 AM

Make sure you have a listen to Nicholas Blumhardt talking about Autofac 2 on the Talking Shop Down Under podcast.

It's Inversion of Control Time! This week Nick Blumhardt talks about IoC containers in general, the problems with the service locator pattern and why constructor injection is considered a better choice, a little about how MEF and Autofac differ in purpose and a lot about Autofac 2's new features.

Nick was also a guest on .NET Rocks! last year, and that episode is definitely worth listening to as well.

The .NET dudes talk to Nicholas Blumhardt about Autofac, an IoC container that uses lambda expressions in C# 3.0 to create components.

Keep spreading the good word Nick!

Tags:

Autofac

About the author

Alex Meyer-Gleaves I'm a Technical Architect living in Australia (that island like continent in the southern hemisphere). I love Microsoft .NET and C#. I hate early mornings, slow drivers and Lotus Notes.

Google Shared

 

Month List

Recent Posts

Recent Comments

Comment RSS

Links

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010