【问题标题】:ASP.NET MVC 6 Controller FactoryASP.NET MVC 6 控制器工厂
【发布时间】:2015-10-02 02:24:44
【问题描述】:

我想从数据库(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>();
    }

【问题讨论】:

  • 这个话题有进展吗?我会很高兴有一个解决方案。

标签: c# asp.net asp.net-mvc asp.net-mvc-4


【解决方案1】:

其实我也有同样的需求,需要用一些自定义的替换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);
    }

大功告成,还可以在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);
        }
    }

修改后就可以这么简单的使用了:

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

那么你可以替换 Mvc 6 Pipeline 上的任何组件;

【讨论】:

    【解决方案2】:
         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());
            }
    

    【讨论】:

    • 解释你的答案!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多