HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Using a BaseController in MVC asp.net to reuse the repository

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
basecontrollerthemvcnetusingreuserepositoryasp

Problem

I have a repository class that impliments a repository Interface.
In my Controllers I want a way to access the repository without creating constructors each time in the controller. So now all my Controllers have to do is inherit from Base. Any pitfalls to this, or how I can write it differently.

public class BaseController : Controller
    {
        public IRepository Repo {get;set;}
        public IStudentRepositroy StudentRepo {get;set;};
      public BaseController() : this(new Repository(),new StudentRepository())
      {

      }
      public BaseController(IRepository repo,IStudentRepository studentRepo)
      {
          Repo = repo;
          StudentRepo = studentRepo;
      }

    }

Solution

This sounds exactly like a desire for Dependency Injection (using an IoC container). ASP.NET MVC is perfectly setup for this already with plenty of containers out there for you to use!

You can still have a base constructor take arguments if you wish but I would try and limit how many.

So your controllers would look like:

public StudentController(IRepository repo,IStudentRepository studentRepo)
        : base(repo)
{
      StudentRepo = studentRepo;
}


So by using the IoC framework these will be automatically resolved to your desired class. By doing this, it opens up the opportunity to more easily inject mock classes into your controllers and further separates them conceptually from implementation detail of the repositories. Although I typically do not Unit test my controllers (as I try to keep them as skinny as possible), it would also make unit testing easier.

Typically you might do this in the Global.ascx or in the App_Start folder. You can get most DI frameworks by using Nuget packages (which I would recommend). There are many out there but here are a couple of examples from ones I have dealt with in the past.

Autofaq

public class AutofaqConfig
{
    public static void Configure()
    {
        var builder = new ContainerBuilder();
        builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();

        RegisterRepositories(builder);

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

    private static void RegisterRepositories(ContainerBuilder builder)
    {       
        builder.RegisterType().As();
        // And any other repositories here
    }
}

And in your global ascx

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();            
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        AutofaqConfig.Configure();
    }
}


Ninject (Using the MVC3 ninject module)

public static class NinjectWebCommon 
{
    private static readonly Bootstrapper bootstrapper = new Bootstrapper();

    /// 
    /// Starts the application
    /// 
    public static void Start() 
    {
        DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
        DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
        bootstrapper.Initialize(CreateKernel);
    }

    /// 
    /// Stops the application.
    /// 
    public static void Stop()
    {
        bootstrapper.ShutDown();
    }

    /// 
    /// Creates the kernel that will manage your application.
    /// 
    /// The created kernel.
    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind().To();

        RegisterServices(kernel);

        // Install our Ninject-based IDependencyResolver into the Web API config
        GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);

        return kernel;
    }

    /// 
    /// Load your modules or register your services here!
    /// 
    /// The kernel.
    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind().To();
    }        
}


Using Unity (Using Unit.MVC4)

public class UnityConfig
{
    #region Unity Container
    private static Lazy container = new Lazy(() =>
    {
        var container = new UnityContainer();
        RegisterTypes(container);
        return container;
    });

    /// 
    /// Gets the configured Unity container.
    /// 
    public static IUnityContainer GetConfiguredContainer()
    {
        return container.Value;
    }
    #endregion

    /// Registers the type mappings with the Unity container.
    /// The unity container to configure.
    /// There is no need to register concrete types such as controllers or API controllers (unless you want to 
    /// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.
    public static void RegisterTypes(IUnityContainer container)
    {
        // NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
        // container.LoadConfiguration();

        // Repositories
        container.RegisterType();
    }
}

Code Snippets

public StudentController(IRepository repo,IStudentRepository studentRepo)
        : base(repo)
{
      StudentRepo = studentRepo;
}
public class AutofaqConfig
{
    public static void Configure()
    {
        var builder = new ContainerBuilder();
        builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();

        RegisterRepositories(builder);

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

    private static void RegisterRepositories(ContainerBuilder builder)
    {       
        builder.RegisterType<StudentRepository>().As<IStudentRepository>();
        // And any other repositories here
    }
}

And in your global ascx

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();            
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        AutofaqConfig.Configure();
    }
}
public static class NinjectWebCommon 
{
    private static readonly Bootstrapper bootstrapper = new Bootstrapper();

    /// <summary>
    /// Starts the application
    /// </summary>
    public static void Start() 
    {
        DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
        DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
        bootstrapper.Initialize(CreateKernel);
    }

    /// <summary>
    /// Stops the application.
    /// </summary>
    public static void Stop()
    {
        bootstrapper.ShutDown();
    }

    /// <summary>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

        RegisterServices(kernel);

        // Install our Ninject-based IDependencyResolver into the Web API config
        GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);

        return kernel;
    }

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<StudentRepository>().To<IStudentRepository>();
    }        
}
public class UnityConfig
{
    #region Unity Container
    private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
    {
        var container = new UnityContainer();
        RegisterTypes(container);
        return container;
    });

    /// <summary>
    /// Gets the configured Unity container.
    /// </summary>
    public static IUnityContainer GetConfiguredContainer()
    {
        return container.Value;
    }
    #endregion

    /// <summary>Registers the type mappings with the Unity container.</summary>
    /// <param name="container">The unity container to configure.</param>
    /// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to 
    /// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
    public static void RegisterTypes(IUnityContainer container)
    {
        // NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
        // container.LoadConfiguration();

        // Repositories
        container.RegisterType<IStudentRepository, StudentRepository>();
    }
}

Context

StackExchange Code Review Q#40102, answer score: 11

Revisions (0)

No revisions yet.