Skip to content

Instantly share code, notes, and snippets.

@janv8000
Created January 12, 2015 13:32
Show Gist options
  • Save janv8000/35e6250c8efc00288d21 to your computer and use it in GitHub Desktop.
Save janv8000/35e6250c8efc00288d21 to your computer and use it in GitHub Desktop.
Start background tasks from MVC actions using Autofac

Start background tasks from MVC actions using Autofac


1/12/2015 2:19:13 PM

Original source

Adapted to latest Autofac and MVC versions:

  • Use InstancePerRequest for a database context
  • Add ILifetimeScope as dependency to get to the container
  • SingleInstance ensures it's the root lifetime scope
  • Use HostingEnvironment.QueueBackgroundWorkItem to reliably run something in the background
  • Use MatchingScopeLifetimeTags.RequestLifetimeScopeTag to avoid having to know the tagname autofac uses for PerRequest lifetimes

https://groups.google.com/forum/#!topic/autofac/gJYDDls981A https://groups.google.com/forum/#!topic/autofac/yGQWjVbPYGM

public interface IAsyncRunner
{
void Run<T>(Action<T> action);
}
public class AsyncRunner : IAsyncRunner
{
public ILifetimeScope LifetimeScope { get; set; }
public AsyncRunner(ILifetimeScope lifetimeScope)
{
Guard.NotNull(() => lifetimeScope, lifetimeScope);
LifetimeScope = lifetimeScope;
}
public void Run<T>(Action<T> action)
{
HostingEnvironment.QueueBackgroundWorkItem(ct =>
{
// Create a nested container which will use the same dependency
// registrations as set for HTTP request scopes.
using (var container = LifetimeScope.BeginLifetimeScope(MatchingScopeLifetimeTags.RequestLifetimeScopeTag))
{
var service = container.Resolve<T>();
action(service);
}
});
}
}
public Controller(IAsyncRunner asyncRunner)
{
Guard.NotNull(() => asyncRunner, asyncRunner);
AsyncRunner = asyncRunner;
}
public ActionResult Index()
{
//Snip
AsyncRunner.Run<ListingService>(listingService => listingService.RenderListing(listingGenerationArguments, Thread.CurrentThread.CurrentCulture));
//Snip
}
protected void Application_Start() {
//Other registrations
builder.RegisterType<ListingService>();
builder.RegisterType<WebsiteContext>().As<IWebsiteContext>().InstancePerRequest(); //WebsiteContext is a EF DbContext
builder.RegisterType<AsyncRunner>().As<IAsyncRunner>().SingleInstance();
}
public class ListingService : IListingService
{
public ListingService(IWebsiteContext context)
{
Guard.NotNull(() => context, context);
Context = context;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment