Startup.Configuration gets called slightly later than Application_Start, but I don't think the difference will matter much in most cases.
I believe the major reasons we kept the other code in Global.asax are:
- Consistency with previous versions of MVC. (That's where everybody currently expects to find this code.)
- Ability to add other event handlers. In Global.asax, you can handle other methods like Session_Start and Application_Error.
- Correctness in a variety of authentication scenarios. The Startup.Configuration method is only called if you have Microsoft.Owin.Host.SystemWeb.dll in your bin directory. If you remove this DLL, it will silently stop calling Startup.Configuration, which could be hard to understand.
I think the third reason is the most important one we didn't take this approach by default, since some scenarios don't include having this DLL, and it's nice to be able to change authentication approaches without invalidating the location where unrelated code (like route registration) is placed.
But if none of those reasons apply in your scenario, I think you'd be fine using this approach.
In ASP.Net MVC you can use the .Net Core DI from NuGet rather than one of the third-party alternatives:-
using Microsoft.Extensions.DependencyInjection
For the MVC Start/Configuration class:-
public void Configuration(IAppBuilder app)
{
// We will use Dependency Injection for all controllers and other classes, so we'll need a service collection
var services = new ServiceCollection();
// configure all of the services required for DI
ConfigureServices(services);
// Configure authentication
ConfigureAuth(app);
// Create a new resolver from our own default implementation
var resolver = new DefaultDependencyResolver(services.BuildServiceProvider());
// Set the application resolver to our default resolver. This comes from "System.Web.Mvc"
//Other services may be added elsewhere through time
DependencyResolver.SetResolver(resolver);
}
My project uses Identity User and I've replaced the OWIN start-up configuration to follow a service-based approach instead. The default Identity User classes use static factory methods to create instances. I've moved that code into the constructors and relied on DI to provide the appropriate injection. It is still work in progress but here is where I am at:-
public void ConfigureServices(IServiceCollection services)
{
//====================================================
// Create the DB context for the IDENTITY database
//====================================================
// Add a database context - this can be instantiated with no parameters
services.AddTransient(typeof(ApplicationDbContext));
//====================================================
// ApplicationUserManager
//====================================================
// instantiation requires the following instance of the Identity database
services.AddTransient(typeof(IUserStore<ApplicationUser>), p => new UserStore<ApplicationUser>(new ApplicationDbContext()));
// with the above defined, we can add the user manager class as a type
services.AddTransient(typeof(ApplicationUserManager));
//====================================================
// ApplicationSignInManager
//====================================================
// instantiation requires two parameters, [ApplicationUserManager] (defined above) and [IAuthenticationManager]
services.AddTransient(typeof(Microsoft.Owin.Security.IAuthenticationManager), p => new OwinContext().Authentication);
services.AddTransient(typeof(ApplicationSignInManager));
//====================================================
// ApplicationRoleManager
//====================================================
// Maps the rolemanager of identity role to the concrete role manager type
services.AddTransient<RoleManager<IdentityRole>, ApplicationRoleManager>();
// Maps the role store role to the implemented type
services.AddTransient<IRoleStore<IdentityRole, string>, RoleStore<IdentityRole>>();
services.AddTransient(typeof(ApplicationRoleManager));
//====================================================
// Add all controllers as services
//====================================================
services.AddControllersAsServices(typeof(Startup).Assembly.GetExportedTypes()
.Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
.Where(t => typeof(IController).IsAssignableFrom(t)
|| t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)));
}
The Account Controller class has the single constructor:-
[Authorize]
public class AccountController : Controller
{
private ApplicationSignInManager _signInManager;
private ApplicationUserManager _userManager;
private RoleManager<IdentityRole> _roleManager;
public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager, RoleManager<IdentityRole> roleManager)
{
UserManager = userManager;
SignInManager = signInManager;
RoleManager = roleManager;
}
}
My Default Dependency Resolver:
/// <summary>
/// Provides the default dependency resolver for the application - based on IDependencyResolver, which hhas just two methods
/// </summary>
public class DefaultDependencyResolver : IDependencyResolver
{
/// <summary>
/// Provides the service that holds the services
/// </summary>
protected IServiceProvider serviceProvider;
/// <summary>
/// Create the service resolver using the service provided (Direct Injection pattern)
/// </summary>
/// <param name="serviceProvider"></param>
public DefaultDependencyResolver(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
/// <summary>
/// Get a service by type - assume you get the first one encountered
/// </summary>
/// <param name="serviceType"></param>
/// <returns></returns>
public object GetService(Type serviceType)
{
return this.serviceProvider.GetService(serviceType);
}
/// <summary>
/// Get all services of a type
/// </summary>
/// <param name="serviceType"></param>
/// <returns></returns>
public IEnumerable<object> GetServices(Type serviceType)
{
return this.serviceProvider.GetServices(serviceType);
}
}
Best Answer
I am not an expert on
Ninject
but as far as i know, i am only using it to link myDataSource Interface
and myEfDb Class
to the rest of my application.If you need a good book that has a Real Application built around
Ninject
try: Pro ASP.NET MVC 3 Framework, Third Editionor
Pro Asp.Net Mvc 4
There are very few lines of code i am usually concerned with
Then register your
NinjectControllerFactory
inGlobal.asax.cs
with:ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
As you can see, this class use
Method Injection
usingprivate void AddBindings()
. This makes it very easy if you are followingTest Driven Development (TDD)