简体   繁体   中英

ASP.NET MVC 6 Controller Factory

I want to create controllers action from database (ASP.NET MVC 6 vNext). I have table controller and also actions action table has properties { ViewPath, ActionName } Where actionName is {Controller}/{ActionName} I want build pages like this. How can i make it? I have class for MVC 4 but I need to rewrite it to MVC 6

public class ITSDefaultController : DefaultControllerFactory
    {

        public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
        {
            try
            {
                return base.CreateController(requestContext, controllerName) as Controller;

            }
            catch (Exception)
            {
                Controller controller = new ITSControllerBase();
                using (var db = new ITS.Database.DatabaseDataContext())
                {
                    string action = requestContext.RouteData.Values["action"] as string;
                    DynamicAction dynamicAction = null;
                    if (!db.Controllers.Any(x => x.ControllerName == controllerName && x.Views.Any(v => v.ViewName == action)))
                    {
                        dynamicAction = Actions["NotFound"].First();
                        requestContext.RouteData.Values["controller"] = "NotFound";
                        requestContext.RouteData.Values["action"] = "Index";
                    }
                    else
                    {
                        dynamicAction = new DynamicAction()
                        {
                            ActionName = db.Views.First(d => d.ViewName == action && d.Controller.ControllerName == controllerName).ViewName,
                            Result = () => new ViewResult()
                        };
                    }


                    if (dynamicAction != null)
                    {
                        controller.ActionInvoker = new DynamicActionInvoker() { DynamicAction = dynamicAction };
                    }

                    return controller;
                }

            }
        }
        public override void ReleaseController(IController controller)
        {
            base.ReleaseController(controller);
        }
        public static ConcurrentDictionary> Actions = new ConcurrentDictionary>();
    }

actually I have the same need to replace Mvc pipeline components by some custom ones, and I found that the IControllerFactory and IControllerActivator and their default implementations still the same, then the experience was to replace the Mvc 6 DefaultControllerFactory by the CustomControllerFactory, I've done some tests on the startup class on ConfigureServices :

    public void ConfigureServices(IServiceCollection services)
    {
       services.AddMvc();
       var serviceDescriptor = services.FirstOrDefault(s => s.ServiceType.FullName.Contains("IControllerFactory"));
       var serviceIndex = services.IndexOf(serviceDescriptor);
       services.Insert(serviceIndex, new ServiceDescriptor(typeof(IControllerFactory), typeof(CustomControllerFactory), ServiceLifeTime.Singleton));
       services.RemoveAt(serviceIndex + 1);
    }

and it s done, also you can add an extension method to the IServiceCollection interface:

    public static class ServiceCollectionExtensions
    {
        public static void(this IServiceCollection services, Type serviceType, Type implementationType, ServiceLifetime serviceLifetime = ServiceLifetime.Singleton)
        {
            var serviceDescriptor = services.FirstOrDefault(s => s.ServiceType == serviceType);
            var serviceIndex = services.IndexOf(serviceDescriptor);
            services.Insert(serviceIndex, new ServiceDescriptor(serviceType, implementationType, serviceLifetime));
            services.RemoveAt(serviceIndex + 1);
        }
    }

after this modification you can use it as simple as this :

    ......
    services.AddMvc();
    services.ReplaceService(typeof(IControllerActivator), typeof(CustomControllerActivator));
    services.ReplaceService(typeof(IControllerFactory), typeof(CustomControllerFactory));
    ......

then you can replace any component on the Mvc 6 Pipeline;

     public class HomeController : Controller
        {
            public string _MyName { get; set; }
            // GET: Home
            public ActionResult Index()
            {
                return Content(_MyName);
            }

            public HomeController(string Name)
            {
                _MyName = Name;
            }
        }


 public class MyCustomController : IControllerFactory
    {
        public IController CreateController(RequestContext requestContext, string controllerName)
        {
            HomeController objHomeController = new HomeController("Any thing Which you want to pass/inject.");
            return objHomeController;
        }

        public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
        {
            return SessionStateBehavior.Default;
        }

        public void ReleaseController(IController controller)
        {
            IDisposable disposable = controller as IDisposable;
            if(disposable!=null)
            {
                disposable.Dispose();
            }
        }
    }



 protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            ControllerBuilder.Current.SetControllerFactory(new MyCustomController());
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM