前言
在ASP.NET MVC的開發中,我們創建完項目之后,ASP.NET MVC是已Model-Controller-View的形式存在的,在創建項目自動生成的內容上Model我們很容易分離成類庫,所以這里不予說明,那么這時候我們就像Controller是不是也能夠分離出去呢?答案是肯定的,下面我們探討一下Controller如何分離出去。
這里我提供兩種分離的方法,一是重寫方法繼承自IControllerFactory接口,實現里面的方法,二是MVC提供了直接在路由注冊里面去控制控制器的書寫,下面就這兩種類型簡單貼一下代碼。
第一種方法
代碼如下:當寫完代碼之后再路由中注冊。提示:實現完成之后必須在路由規則方法(RegisterRoutes)里面進行注冊,注冊代碼如下:
ControllerBuilder.Current.SetControllerFactory(new ControllersFactory("BookSystem_Controllers")); //BookSystem_Controllers為控制器的類庫
1 // 源文件頭信息: 2 // <copyright file="ControllersFactory.cs"> 3 // Copyright(c)2014-2034 Kencery.All rights reserved. 4 // 個人博客:http://www.cnblogs.com/hanyinglong 5 // 創建人:韓迎龍(kencery) 6 // 創建時間:2015-6-18 7 // </copyright> 8 9 using System; 10 using System.Reflection; 11 using System.Web.Mvc; 12 using System.Web.Routing; 13 using System.Web.SessionState; 14 15 namespace BookSystem_Controllers 16 { 17 /// <summary> 18 /// 重寫注冊控制器的方法,使之能夠將控制器管分離到其它類庫中實現 19 /// <auther> 20 /// <name>kencery</name> 21 /// <date>2015-6-18</date> 22 /// </auther> 23 /// </summary> 24 /// 說明:IControllerFactory接口含有三個需要實現的方法:CreateController,GetControllerSessionBehavior,ReleaseController 25 /// 使用:在MVC App_Start文件夾中的RouteConfig中的方法RegisterRoutes中的第一行中寫入下面注冊語句,Global.asax中也可注冊,放到注冊路由之前即可 26 /// ControllerBuilder.Current.SetControllerFactory(new ControllersFactory("BookSystem_Controllers")); //BookSystem_Controllers為控制器的類庫 27 public class ControllersFactory : IControllerFactory 28 { 29 private readonly string _assemblyName; 30 private readonly string _controlerDefaultNameSpage; 31 private Assembly _controllerAssembly; 32 33 /// <summary> 34 /// 獲取控制器所在的程序集名稱 35 /// </summary> 36 public string AssemblyName 37 { 38 get { return _assemblyName; } 39 } 40 41 /// <summary> 42 /// 獲取控制器的默認命名空間 43 /// </summary> 44 public string ControlerDefaultNameSpage 45 { 46 get { return _controlerDefaultNameSpage; } 47 } 48 49 /// <summary> 50 /// 獲取控制器所在的程序集的Assembly實例 51 /// </summary> 52 public Assembly ControllerAssembly 53 { 54 get 55 { 56 return _controllerAssembly ?? (_controllerAssembly = Assembly.Load(AssemblyName)); //加載控制器信息 57 } 58 } 59 60 /// <summary> 61 /// 構造函數實例化 62 /// </summary> 63 /// <param name="assemblyName"></param> 64 public ControllersFactory(string assemblyName) 65 { 66 _assemblyName = assemblyName; 67 } 68 69 /// <summary> 70 /// 構造函數實例化 71 /// </summary> 72 /// <param name="assemblyName"></param> 73 /// <param name="controlerDefaultNameSpage"></param> 74 public ControllersFactory(string assemblyName, string controlerDefaultNameSpage) 75 { 76 _assemblyName = assemblyName; 77 _controlerDefaultNameSpage = controlerDefaultNameSpage; 78 } 79 80 /// <summary> 81 /// 獲取控制器類的全名 82 /// </summary> 83 /// <param name="controllerName">控制器名稱</param> 84 public string GetControllerFullName(string controllerName) 85 { 86 return string.Format("{0}.{1}Controller", 87 string.IsNullOrEmpty(ControlerDefaultNameSpage) ? AssemblyName : ControlerDefaultNameSpage, 88 controllerName); 89 } 90 91 /// <summary> 92 /// 獲取控制器實例對象,根據controllerName生成一個沒有請求上下文對象的空的控制器,在為此控制器制定ControllerContext對象,然后返回控制器實例 93 /// </summary> 94 /// <param name="requestContext"></param> 95 /// <param name="controllerName"></param> 96 public IController CreateController(RequestContext requestContext, string controllerName) 97 { 98 var controller = ControllerAssembly.CreateInstance(GetControllerFullName(controllerName)) as Controller; 99 if (controller == null) 100 return null; 101 if (controller.ControllerContext == null) 102 { 103 controller.ControllerContext = new ControllerContext(requestContext, controller); 104 } 105 else 106 { 107 controller.ControllerContext.RequestContext = requestContext; 108 } 109 return controller; 110 } 111 112 /// <summary> 113 /// 返回請求的會話狀態的支持類型 114 /// </summary> 115 /// <param name="requestContext"></param> 116 /// <param name="controllerName"></param> 117 public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName) 118 { 119 var controllerType = ControllerAssembly.GetType(GetControllerFullName(controllerName), true, true); 120 var sessionStateAttr = 121 Attribute.GetCustomAttribute(controllerType, typeof (SessionStateAttribute), false) as 122 SessionStateAttribute; 123 return sessionStateAttr == null ? SessionStateBehavior.Default : sessionStateAttr.Behavior; 124 } 125 126 /// <summary> 127 /// 釋放資源 128 /// </summary> 129 /// <param name="controller"></param> 130 public void ReleaseController(IController controller) 131 { 132 var idDisposable = controller as IDisposable; 133 if (idDisposable != null) 134 { 135 idDisposable.Dispose(); 136 } 137 } 138 } 139 }
第二種方法
路由注冊方法代碼如下:缺點是,如果有多個注冊路由的規則,都必須記得添加namespaces屬性,否則會出現錯誤
1 //系統默認路由 2 routes.MapRoute( 3 name: "Default", 4 url: "{controller}/{action}/{id}", 5 defaults: new {controller = "Login", action = "Index", id = UrlParameter.Optional}, 6 namespaces: new string[] {"BookSystem_Controllers"} 7 );
第三種方法
第三種方法是我這段時間建立MVC項目使用的方法,不像上面那么復雜,只要namespace命名等規范,其實在MVC項目下的Controller就是DLL文件,所以當我們將控制器分離成類庫移除去的時候,直接在MVC項目中添加DLL文件即可實現分離