I've setup a series of tasks using the Application events in a global.asax.cs file like so:
// Note: For instructions on enabling IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=301868
public class MvcApplication : System.Web.HttpApplication
{
private static IContainer ContainerGlobal;
private static ILogger Logger;
public ILifetimeScope Container
{
get { return (ILifetimeScope)HttpContext.Current.Items["_Container"]; }
set { HttpContext.Current.Items["_Container"] = value; }
}
protected void Application_Start()
{
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
//configure the Autofac IoC container
var container = AutofacBuilder.Configure(Assembly.GetExecutingAssembly(),
new MvcModule(), new TaskModule());
// startup the logging
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase)
.Replace("file:\\", string.Empty);
var file = new FileInfo(path + @"\log4net.ui.config");
Logger = new Logger(MethodBase.GetCurrentMethod().DeclaringType, file);
var runAtInits = container.Resolve<IEnumerable<IRunAtInit>>();
if (runAtInits != null)
{
Logger.LogFormat(LogType.Debug, "Found {0} IRunAtInit instances",
runAtInits.Count());
foreach (var task in runAtInits)
{
task.Execute();
}
}
var runAtStartups = container.Resolve<IEnumerable<IRunAtStartup>>();
if (runAtStartups != null)
{
Logger.LogFormat(LogType.Debug, "Found {0} IRunAtStartup instances",
runAtStartups.Count());
foreach (var task in runAtStartups)
{
task.Execute();
}
}
ContainerGlobal = container;
}
public void Application_BeginRequest()
{
try
{
Container = ContainerGlobal.BeginLifetimeScope();
var runOnEachRequests =
Container.Resolve<IEnumerable<IRunOnEachRequest>>();
if (runOnEachRequests == null)
return;
Logger.LogFormat(LogType.Debug, "Found {0} IRunOnEachRequest instances",
runOnEachRequests.Count());
foreach (var task in runOnEachRequests)
{
task.Execute();
}
}
catch(Exception ex)
{
Logger.Log(LogType.Error, ex);
}
}
public void Application_Error()
{
try
{
var runOnErrors = Container.Resolve<IEnumerable<IRunOnError>>();
if (runOnErrors == null)
return;
Logger.LogFormat(LogType.Debug, "Found {0} IRunOnError instances",
runOnErrors.Count());
foreach (var task in runOnErrors)
{
task.Execute();
}
}
catch (Exception ex)
{
Logger.Log(LogType.Error, ex);
}
}
public void Application_EndRequest()
{
try
{
var runAfterEachRequests =
Container.Resolve<IEnumerable<IRunAfterEachRequest>>();
if (runAfterEachRequests == null)
return;
Logger.LogFormat(LogType.Debug, "Found {0} IRunAfterEachRequest instances",
runAfterEachRequests.Count());
foreach (var task in runAfterEachRequests)
{
task.Execute();
}
}
catch (Exception ex)
{
Logger.Log(LogType.Error, ex);
}
finally
{
if (Container != null)
{
Container.Dispose();
Container = null;
}
}
}
}
This is discussed by Matt Honeycut here:
https://github.com/MattHoneycutt/Fail-Tracker
As we make extensive use of Autofac throughout our application, we've implemented it using Autofac rather than Structuremap.
The problem is, we get exceptions raised for the following events: Application_EndRequest and sometimes for Application_BeginRequest. The exception raised in both cases is:
"No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself"
We've ensured that we use the ILifeScope for our Container object, rather than the root Container object. However, this doesn't fix the errors. Does anyone else have any suggestions as to what else we need to do?
For information, the call to AutofacBuilder.Configure above registers all necessary library types and modules and returns the root Container from autofac by calling the Build method.
thanks
PS We're using: Visual Studio 2013, MVC 5.1 Autofac 3.3