Search code examples
asp.net-core-mvccontroller-factory

Modify ControllerContext in CreateController method of DefaultControllerFactory in asp.net core mvc


  • I want to override my controllers method. Here i have overriden CreateController method of DefaultControllerFactory to return the CatalogCustomController object if request come for CatalogController.

But the problem is here that i need to pass all the dependency into controller constructor.

 public class CustomControllerFactory: DefaultControllerFactory
{  
    public CustomControllerFactory(ICatalogModelFactory catalogModelFactory,
        IProductModelFactory productModelFactory,
        IControllerActivator controllerActivator, IEnumerable<IControllerPropertyActivator> propertyActivators)
        :base(controllerActivator, propertyActivators)
    {
        this._catalogModelFactory = catalogModelFactory;
        this._productModelFactory = productModelFactory;
    }
    public override object CreateController(ControllerContext context)
    {
        if (context.ActionDescriptor.ControllerTypeInfo.AsType() == typeof(CatalogController))
        {
            return new CatalogCustomController(_catalogModelFactory,
            _productModelFactory,
            _categoryService, 
        }

        return base.CreateController(context);
    }
}

While i want to do it something like this, by modifying ControllerContext context

 public override object CreateController(ControllerContext context)
    {
        if (context.ActionDescriptor.ControllerTypeInfo.AsType() == typeof(CatalogController))
        {

            context.ActionDescriptor.ControllerName = "CatalogCustomController";   
        }

        return base.CreateController(context);
    }

Solution

  • You could try register Controller into IServiceCollection, and then retrieve Controller from IServiceCollection in CreateController.

    1. Extension method for AddControllersAsServices

      public static class Extension
      {
      public static IMvcBuilder AddControllersAsServices(this IMvcBuilder builder)
      {
          var feature = new ControllerFeature();
          builder.PartManager.PopulateFeature(feature);
      
          foreach (var controller in feature.Controllers.Select(c => c.AsType()))
          {
              builder.Services.TryAddTransient(controller, controller);
          }
      
          builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
      
          return builder;
      }
      }
      
    2. Register Services

          services.AddMvc()
              .AddControllersAsServices();
      
    3. CustomControllerFactory

       public class CustomControllerFactory : DefaultControllerFactory
       {
      public CustomControllerFactory(
          IControllerActivator controllerActivator, IEnumerable<IControllerPropertyActivator> propertyActivators)
          : base(controllerActivator, propertyActivators)
      {
      }
      public override object CreateController(ControllerContext context)
      {
          if (context.ActionDescriptor.ControllerTypeInfo.AsType() == typeof(CatalogController))
          {               
              return context.HttpContext.RequestServices.GetRequiredService(typeof(CatalogCustomController));
          }
      
          return base.CreateController(context);
      }
      }