Dependency Injection in ASP.net Session_Start Method

I am learning dependency injection and am using autofac for the first time. I built the container as indicated in several autofac examples (see below) and called application_start from my application

public class ContainerConfig { public static void RegisterContainer() { //Create a new ContainerBuilder var builder = new ContainerBuilder(); // Register all the controllers using the assembly object builder.RegisterControllers(Assembly.GetExecutingAssembly()); //Registering default convention -- IExample and Example builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()) .Where(t => t.Name.Single(i => i.Name == "I" + t.Name)) .AsImplementedInterfaces(); //Build the container var container = builder.Build(); //Set the default resolver to use Autofac DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); } } 

I created a UserService in my main project using IUserService. It has methods to make dbcall to get user information from tables. In my user interface project, I have a UserProvider class that I bind to in order to introduce a UserService.

 public class UserProvider { private readonly IUserService _userService; public UserProvider(IUserService userService) { _userService = userService; } public void LoadCurrentUser() { Users FoundUser = _userService.ImportOrGetUser(); if (FoundUser != null) { //add it to session CurrentUser = FoundUser; } } } 

This UserProvider that I use in session_start session

 void Session_OnStart() { UserProvider OUsrPrv = new UserProvider(new UserService()); OUsrPrv.LoadCurrentUser(); } 

In the above code, if I pass the "new UserService ()", I understand that I entered UserService manually. I do not see how autofac helps here. All google examples talk about dependency injection in MVCController or WebApiController, and not in a separate class (UserProvider), as I do.

Can someone shed some light? Am I doing all this wrong?

+3
c # dependency-injection asp.net-mvc autofac
source share
2 answers

The event model in System.Web.HttpApplication is part of ASP.NET, not MVC. It is not intended for use with dependency injection.

The answer proposed by Cyril uses the service locator to get a link to this service. This is far from ideal, since you depend on the service locator in your code.

An MVC-oriented way of implementing cross-cutting issues (for example, loading user data into session state) is to use globally registered filters. You can implement IAuthorizationFilter or IActionFilter to get the desired effect. In this case, it makes sense to use IActionFilter , since you want to wait until you are sure that there is an authorized user before calling him.

NOTE. . Although this answers your specific question, it is best not to use the session state for this scenario in MVC. An alternative is to use the ASP.NET ID with claims to store user profile data instead of using a session.

 using System; using System.Web.Mvc; using System.Security.Principal; public class GetUserActionFilter : IActionFilter { private readonly IUserRepository userRepository; public GetUserActionFilter(IUserRepository userRepository) { if (userRepository == null) throw new ArgumentNullException("userRepository"); this.userRepository = userRepository; } public void OnActionExecuted(ActionExecutedContext filterContext) { // Do nothing - this occurs after the action method has run } public void OnActionExecuting(ActionExecutingContext filterContext) { IPrincipal user = filterContext.HttpContext.User; if (user == null) { return; } IIdentity identity = user.Identity; if (identity == null) { return; } // Make sure we have a valid identity and it is logged in. if (identity.IsAuthenticated) { string key = "__CurrentUserData"; var userData = filterContext.HttpContext.Session[key]; if (userData == null) { // User data doesn't exist in session, so load it userData = userRepository.GetUserData(identity.Name); // Add it to session state filterContext.HttpContext.Session[key] = userData; } } } } 

Now, to add your filter worldwide, you need to:

  • Register the filter and its dependencies with Autofac.
  • Pass the container to the static RegisterGlobalFilters method.

Register a filter

Using a named instance to distinguish it from other potential IActionFilter instances.

 builder.RegisterType<GetUserActionFilter>() .Named<IActionFilter>("getUserActionFilter"); 

Skip container

FilterConfig.cs

 public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters, IContainer container) { filters.Add(container.ResolveNamed<IActionFilter>("getUserActionFilter")); filters.Add(new HandleErrorAttribute()); } } 

Global.asax.cs

 public class MvcApplication : System.Web.HttpApplication { // This method serves as the composition root // for the project. protected void Application_Start() { // Register Autofac DI IContainer container = ContainerConfig.RegisterContainer(); AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters, container); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); AuthConfig.RegisterAuth(); } } 

ContainerConfig.cs

 public class ContainerConfig { public static IContainer RegisterContainer() { //Create a new ContainerBuilder var builder = new ContainerBuilder(); // Register all the controllers using the assembly object builder.RegisterControllers(Assembly.GetExecutingAssembly()); //Registering default convention -- IExample and Example builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()) .Where(t => t.Name.Single(i => i.Name == "I" + t.Name)) .AsImplementedInterfaces(); // Register our filter builder.RegisterType<GetUserActionFilter>() .Named<IActionFilter>("getUserActionFilter"); //Build the container var container = builder.Build(); //Set the default resolver to use Autofac DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); // Return the container to our composition root. return container; } } 

Please note that I just used the repository service here, since the HttpContext is already accessible through the action filter, and additional logic is needed here, because we don’t know exactly whether it exists in the session state or not, or not even the user to search, therefore our filter performs these checks in addition to loading session state.

+2
source share

To use Injection Dependency correctly, you should never create an instance yourself, the basic structure should provide you with instances.

But ASP.net calls Session_OnStart without any dependency injection. In this case, you can use the static property DependencyResolver.Current to resolve the requested service.

 void Session_OnStart() { UserProvider userProvider = DependencyResolver.Current.GetService<UserProvider>(); userProvider.LoadCurrentUser(); } 
+3
source share

All Articles