(1-1)文件结构的升级(Area和Filter知识总结) - ASP.NET从MVC5升级到MVC6
ASP.NET從MVC5升級到MVC6 總目錄
MVC5項目結構
帶有Areas和Filter的項目結構
一般來說,小的MVC項目是不考慮領域的,但是,如果是稍微復雜一點的項目,往往是需要領域這個概念的。
一個領域就是一個小型的MVC項目,所以領域Area的目錄結構和普通的目錄結構是一樣的。(具有Controllers和Views目錄,以及一個AreaRegistration文件)
一個MVC項目,Controllers和Views這兩個目錄由于約定的關系,文件夾的名稱和相對位置是不能變化的。
在默認的配置下,Controllers下面的Controller和Views下面的子文件夾是一一對應的。Controller里面的方法和View下面的CSHTML視圖也是一一對應的。
Model這個文件夾不是必須的,而且按照趨勢,Model一般被歸為BussinessLogic,往往存在于業務的工程中。數據模型的問題,這里不進行討論。
AreaRegistration文件
一個AreaRegistration文件是這樣的: AdminAreaRegistration.cs 請注意命名規范,MVC這樣的約定氛圍很濃重的框架,最好按照規定命名。
using System.Web.Mvc;namespace WebSite.Areas.Admin {public class AdminAreaRegistration : AreaRegistration{public override string AreaName{get { return "Admin"; }}public override void RegisterArea(AreaRegistrationContext context){context.MapRoute("Admin_default","Admin/{controller}/{action}/{id}",new {controller = "Home", action = "Index", id = UrlParameter.Optional});}} }當然使得這個Area注冊生效的源頭是Global.asax 里面的 RegisterAllAreas 方法
public class MvcApplication : HttpApplication{protected void Application_Start(){//MVCAreaRegistration.RegisterAllAreas();GlobalConfiguration.Configure(WebApiConfig.Register);FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);RouteConfig.RegisterRoutes(RouteTable.Routes);RouteConfig.cs(位于App_Start文件夾下面)可以設定默認的領域。
using System.Web.Mvc; using System.Web.Routing;namespace WebSite {public class RouteConfig{public static void RegisterRoutes(RouteCollection routes){routes.IgnoreRoute("{resource}.axd/{*pathInfo}");routes.MapRoute("Default", "{area}/{controller}/{action}/{id}",new {area = "Admin", controller = "Home", action = "Index", id = UrlParameter.Optional},new[] {"WebSite.Areas.Admin.*"}).DataTokens.Add("area", "Admin");}} }Filter
Filter也不是MVC的標配,但是往往一個復雜的項目會有一些Filter。Filter可以完成很多不同的工作,對于某個環節的輸入和輸出進行一些干預。當然Filter也必須注冊才能使用。FilterConfig.cs
using System.Web.Mvc;namespace WebSite {public class FilterConfig{public static void RegisterGlobalFilters(GlobalFilterCollection filters){//默認錯誤處理filters.Add(new HandleErrorAttribute());//日志filters.Add(new LoggerAttribute());//異常記錄filters.Add(new ExceptionHandlerAttribute());//壓縮filters.Add(new CompressAttribute());}} }壓縮
using System.IO.Compression; using System.Web.Mvc;namespace WebSite {OnActionExecuting的時候,可以設定輸出的壓縮public class CompressAttribute : ActionFilterAttribute{public override void OnActionExecuting(ActionExecutingContext filterContext){var acceptEncoding = filterContext.HttpContext.Request.Headers["Accept-Encoding"];if (!string.IsNullOrEmpty(acceptEncoding)){acceptEncoding = acceptEncoding.ToLower();var response = filterContext.HttpContext.Response;if (acceptEncoding.Contains("gzip")){response.AppendHeader("Content-encoding", "gzip");response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);}else if (acceptEncoding.Contains("deflate")){response.AppendHeader("Content-encoding", "deflate");response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);}}}} }錯誤處理
OnException 出現錯誤的時候可以進行一些處理
using System.Web.Mvc; using InfraStructure.Log; using InfraStructure.Utility;namespace WebSite {public class ExceptionHandlerAttribute : HandleErrorAttribute{public override void OnException(ExceptionContext actionExecutedContext){var actionName = actionExecutedContext.RouteData.Values["action"].ToString();var controllerName = actionExecutedContext.RouteData.Values["controller"].ToString();var username = string.Empty;if (actionExecutedContext.HttpContext.Session[ConstHelper.Username] != null){username = actionExecutedContext.HttpContext.Session[ConstHelper.Username].ToString();}ExceptionLog.Log(username, actionName, controllerName, actionExecutedContext.Exception.StackTrace);}} }日志
如果希望每個Action都有執行日志可以這樣,OnActionExecuted之后,可以添加一些動作
using System.Web.Mvc; using InfraStructure.Log; using InfraStructure.Utility;namespace WebSite {public class LoggerAttribute : ActionFilterAttribute{public override void OnActionExecuted(ActionExecutedContext filterContext){var actionName = filterContext.ActionDescriptor.ActionName;var controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;var username = string.Empty;if (filterContext.HttpContext.Session[ConstHelper.Username] != null){username = filterContext.HttpContext.Session[ConstHelper.Username].ToString();}InfoLog.Log(username, actionName, controllerName);}} }安全
如果每個Controller都進行相同的安全檢查,代碼量很龐大,可以設定一個SecurityController,然后所有的Controller都繼承與SecurityController。
using InfraStructure.Helper; using InfraStructure.Log; using InfraStructure.Table; using InfraStructure.Utility;namespace WebSite.Areas.Admin.Controllers {public class DataViewSetController : SecurityController{// GET: Develop/DataViewSetpublic ActionResult Index(){var list = OwnerTableOperator.GetRecListByOwnerId<DataViewSet>(DataViewSet.CollectionName, OwnerId);//MasterTable Sort Function//list.Sort((x, y) => { return x.Rank - y.Rank; });ViewData.Model = list;return View();}本質上還是在運行Action的時候(OnActionExecuting),進行一些搶先過濾。
using System.Web.Mvc; using BussinessLogic.Security; using InfraStructure.Utility;namespace WebSite {public class SecurityController : Controller{/// <summary>/// 驗證/// </summary>/// <param name="filterContext"></param>protected override void OnActionExecuting(ActionExecutingContext filterContext){if (Session[ConstHelper.OwnerId] == null){filterContext.Result = RedirectToAction("Index", "Home", new { area = "Admin" });return;}OwnerId = Session[ConstHelper.OwnerId].ToString();EmployeeInfoType = Session[ConstHelper.EmployeeInfoType].ToString();Username = Session[ConstHelper.Username].ToString();AccountCode = Session[ConstHelper.Account].ToString();Privilege = Session[ConstHelper.Privilege].ToString().GetEnum(PrivilegeType.None);ViewBag.Privilege = Privilege;ViewBag.OwnerId = OwnerId;}} }MVC6
Area
如果你上網檢索關于Area的信息,下面的文章大概會引起你的關注,可惜里面的Sample已經沒有了。
using areas in asp-net-5
如果你想完整的看一個MVC6帶有Area的例子,MusicStore則應該可以滿足你的需求。
MusicStore示例
Area的目錄結構還是和MVC5一樣:MusicStore/Areas/Admin/
這個也沒有什么好修改的。至于Area的路由問題,將在路由里面進一步討論。
Filter
下面這篇文章很好的介紹了Filter的問題,目錄結構還是和MVC5一樣(原作者已經更新到RC2了)
asp-net-5-action-filters
Because the filters will be used as a ServiceType, the different custom filters need to be registered with the framework IoC. If the action filters were used directly, this would not be required.
這里也是需要為Filter進行注冊了,只是注冊的方式變成下面的方式:
public void ConfigureServices(IServiceCollection services) {services.AddMvc();services.AddScoped<ConsoleLogActionOneFilter>();services.AddScoped<ConsoleLogActionTwoFilter>();services.AddScoped<ClassConsoleLogActionOneFilter>(); }工具制作(計劃中)
界面和整體流程
我在考慮是否要做這樣一個工具:
工具的界面如下所示,兩個文本框,一個是MVC5目錄,一個是MVC6目錄。一個升級按鈕。
然后一鍵可以將MVC5 盡可能 得升級到MVC6。
整體工具的框架也很簡單
/// <summary>/// Start To Upgrade MVC5 to MVC6/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btnUpgrade_Click(object sender, EventArgs e){//測試用開始txtMVC5Root.Text = @"E:\WorkSpace\DominoHR\WebSite";txtMVC6Root.Text = @"E:\WorkSpace\MVCMigratiorLib";//測試用結束SystemManager.mvc5Root = txtMVC5Root.Text;SystemManager.mvc6Root = txtMVC6Root.Text;//Init(Log準備)SystemManager.Init();//Analyze The FolderStructureAnalyze.Analyze();//UpgradeMainUpgrade.Upgrade();//Terminte(Log關閉)SystemManager.Terminate();}這里的代碼省略LOG輸出等次要但是必須的功能介紹,一個好的工具必須有LOG。同時,這個工具不能對原來的MVC5文件進行任何的修改,這個是大原則,所有的文件都必須復制到新的目錄下面進行修改
在考慮MVC6的目錄之前,我們先來看看如何分析MVC5的目錄結構。
這里很簡單,就是把頂層目錄都遍歷一遍即可,沒有什么技術含量。當然,由于目錄信息都保存起來了,很容易做出HasArea,HasFilter這樣的屬性方法。
本文已經同步到 http://www.codesnippet.info/Article/Index?ArticleId=00000024
ASP.NET從MVC5升級到MVC6 總目錄
轉載于:https://www.cnblogs.com/TextEditor/p/5507770.html
總結
以上是生活随笔為你收集整理的(1-1)文件结构的升级(Area和Filter知识总结) - ASP.NET从MVC5升级到MVC6的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 入门视频采集与处理(BT656简介) 转
- 下一篇: 物联网监测之光纤振动传感器