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

1.1k Views Asked by At
  • 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);
    }
2

There are 2 best solutions below

1
On BEST ANSWER

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);
    }
    }
    
0
On

I found a solution to do it without registering the controllers as service.

  • Inherit the custom controller from main one.
  • In custom controller factory, get the type of requested controller.
  • Replace the ControllerTypeInfo with the custom one

public override object CreateController(ControllerContext context)
    {
        Type typeOfController = context.ActionDescriptor.ControllerTypeInfo.UnderlyingSystemType;

if (typeOfController == typeof(Nop.Web.Controllers.CatalogController)) { context.ActionDescriptor.ControllerTypeInfo = typeof(Controllers.CatalogCustomController).GetTypeInfo(); } else if (typeOfController == typeof(Nop.Web.Areas.Admin.Controllers.ProductController)) { context.ActionDescriptor.ControllerTypeInfo = typeof(Areas.Admin.Controllers.ProductCustomController).GetTypeInfo(); } return base.CreateController(context); }<pre>