博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(1-1)文件结构的升级(Area和Filter知识总结) - ASP.NET从MVC5升级到MVC6
阅读量:6457 次
发布时间:2019-06-23

本文共 9398 字,大约阅读时间需要 31 分钟。

MVC5项目结构

带有Areas和Filter的项目结构

一般来说,小的MVC项目是不考虑领域的,但是,如果是稍微复杂一点的项目,往往是需要领域这个概念的。

一个领域就是一个小型的MVC项目,所以领域Area的目录结构和普通的目录结构是一样的。(具有Controllers和Views目录,以及一个AreaRegistration文件)
一个MVC项目,Controllers和Views这两个目录由于约定的关系,文件夹的名称和相对位置是不能变化的。
在默认的配置下,Controllers下面的Controller和Views下面的子文件夹是一一对应的。Controller里面的方法和View下面的CSHTML视图也是一一对应的。
Model这个文件夹不是必须的,而且按照趋势,Model一般被归为BussinessLogic,往往存在于业务的工程中。数据模型的问题,这里不进行讨论。

Thumbnail?filename=00000003_20160516155336_FolderMVC5.PNG

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()        {            //MVC            AreaRegistration.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/DataViewSet        public ActionResult Index()        {            var list = OwnerTableOperator.GetRecListByOwnerId
(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    {        ///         ///     验证        ///         ///         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已经没有了。

如果你想完整的看一个MVC6带有Area的例子,MusicStore则应该可以满足你的需求。

Area的目录结构还是和MVC5一样:MusicStore/Areas/Admin/

这个也没有什么好修改的。至于Area的路由问题,将在路由里面进一步讨论。

Filter

下面这篇文章很好的介绍了Filter的问题,目录结构还是和MVC5一样(原作者已经更新到RC2了)

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
(); services.AddScoped
(); services.AddScoped
();}

工具制作(计划中)

界面和整体流程

我在考虑是否要做这样一个工具:

工具的界面如下所示,两个文本框,一个是MVC5目录,一个是MVC6目录。一个升级按钮。
然后一键可以将MVC5 尽可能 得升级到MVC6。

Thumbnail?filename=00000003_20160516163239_ToolImage001.PNG

整体工具的框架也很简单

///         ///     Start To Upgrade MVC5 to MVC6        ///         ///         ///         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 Folder            StructureAnalyze.Analyze();            //Upgrade            MainUpgrade.Upgrade();            //Terminte(Log关闭)            SystemManager.Terminate();        }

这里的代码省略LOG输出等次要但是必须的功能介绍,一个好的工具必须有LOG。同时,这个工具不能对原来的MVC5文件进行任何的修改,这个是大原则,所有的文件都必须复制到新的目录下面进行修改

在考虑MVC6的目录之前,我们先来看看如何分析MVC5的目录结构。

这里很简单,就是把顶层目录都遍历一遍即可,没有什么技术含量。当然,由于目录信息都保存起来了,很容易做出HasArea,HasFilter这样的属性方法。

///         /// Has Areas        ///         public static bool HasAreas {            get {                return RootFolder.ContainsKey(strAreas);            }        }        ///         /// Analyze         ///         public static void Analyze() {            //Get Top Level Folder List            foreach (var topLevelFolder in Directory.GetDirectories(SystemManager.mvc5Root))            {                string folderName = new FileInfo(topLevelFolder).Name;                RootFolder.Add(folderName, topLevelFolder);                SystemManager.Log("topLevelFolder:" + folderName);            }            AppendReport();        }

本文已经同步到 http://www.codesnippet.info/Article/Index?ArticleId=00000024

转载地址:http://jfizo.baihongyu.com/

你可能感兴趣的文章
bzoj1106[POI2007]立方体大作战tet*
查看>>
spring boot configuration annotation processor not found in classpath问题解决
查看>>
【转】正则基础之——神奇的转义
查看>>
团队项目测试报告与用户反馈
查看>>
对软件工程课程的期望
查看>>
Mysql中文字符串提取datetime
查看>>
CentOS访问Windows共享文件夹的方法
查看>>
IOS 与ANDROID框架及应用开发模式对比一
查看>>
由中序遍历和后序遍历求前序遍历
查看>>
我学习参考的网址
查看>>
easyui的combotree以及tree,c#后台异步加载的详细介绍
查看>>
1、串(字符串)以及串的模式匹配算法
查看>>
[Processing]点到线段的最小距离
查看>>
考研随笔2
查看>>
ubuntu Linux 操作系统安装与配置
查看>>
乱码的情况
查看>>
虚拟机centos 同一个tomcat、不同端口访问不同的项目
查看>>
在不花一分钱的情况下,如何验证你的创业想法是否可行?《转》
查看>>
Linux/Android 性能优化工具 perf
查看>>
GitHub使用教程、注册与安装
查看>>