ASP.NET MVC 6控制器工厂

Giv*_*ili 6 c# asp.net asp.net-mvc asp.net-mvc-4

我想从数据库创建控制器操作(ASP.NET MVC 6 vNext).我有表控制器和动作动作表有属性{ ViewPath, ActionName }其中actionName是{Controller}/{ActionName} 我想要这样的构建页面.我该怎么做?我有MVC 4课程,但我需要将其重写为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>();
    }
Run Code Online (Sandbox Code Playgroud)

Mou*_*oui 0

实际上我也有同样的需要用一些自定义的替换Mvc管道组件,并且我发现IControllerFactory和IControllerActivator及其默认实现仍然相同,然后经验是用CustomControllerFactory替换Mvc 6 DefaultControllerFactory,我已经完成了对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);
    }
Run Code Online (Sandbox Code Playgroud)

这样就完成了,您还可以向 IServiceCollection 接口添加扩展方法:

    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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

修改后,您可以像这样简单地使用它:

    ......
    services.AddMvc();
    services.ReplaceService(typeof(IControllerActivator), typeof(CustomControllerActivator));
    services.ReplaceService(typeof(IControllerFactory), typeof(CustomControllerFactory));
    ......
Run Code Online (Sandbox Code Playgroud)

然后您可以替换 Mvc 6 Pipeline 上的任何组件;