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

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

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

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

        /// <summary>
/// Has Areas
/// </summary>
public static bool HasAreas {
get {
return RootFolder.ContainsKey(strAreas);
}
} /// <summary>
/// Analyze
/// </summary>
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

ASP.NET从MVC5升级到MVC6 总目录

(1-1)文件结构的升级(Area和Filter知识总结) - ASP.NET从MVC5升级到MVC6的更多相关文章

  1. ASP.NET从MVC5升级到MVC6 RC2 总目录 - 发布在RC2Release之后

    序言 随着MVC6RC2的推出,MVC6的脚步越来越近了.但是在我们的手里,有大批量的MVC5的项目.如何将MVC5升级到MVC6,将是一个很大的课题.微软官方暂时没有一个升级指导,或者一个迁移工具, ...

  2. ASP.NET从MVC5升级到MVC6

    1-1)文件结构的升级(Area和Filter知识总结) - ASP.NET从MVC5升级到MVC6   ASP.NET从MVC5升级到MVC6 总目录 MVC5项目结构 带有Areas和Filter ...

  3. (0)ASP.NET Core 简单介绍 和开发环境搭建 - ASP.NET从MVC5升级到MVC6

    ASP.NET从MVC5升级到MVC6 总目录 ASP.NET Core 首先,ASP原本只是一种技术,这种技术从上个世纪90年代就有了. Active Service Page 和 Java Ser ...

  4. (1-2)配置的升级 - ASP.NET从MVC5升级到MVC6

    ASP.NET从MVC5升级到MVC6 总目录 MVC5和MVC6的区别 在MVC5的时候,web.config文件无疑是整个配置的核心,从web配置,到应用程序的参数,都可以写在web.config ...

  5. SQL 2008升级SQL 2008 R2完全教程或者10.00.1600升级10.50.1600

    http://blog.csdn.net/feng19821209/article/details/8571571 SQL 2008升级SQL 2008 R2完全教程或者10.00.1600升级10. ...

  6. SQL 2008升级SQL 2008 R2完全教程或者10.00.4000升级10.50.1600

    今天将由于需要就将我的SQL 2008升级到SQL 2008 R2. 说到为什么要升级是因为,从另一台机器上备份了一个数据库,到我的机器上还原的时候提示“System.Data.SqlClient.S ...

  7. Linux包系列的知识(附:Ubuntu16.04升级到18.04的案例)

    Linux基础:https://www.cnblogs.com/dunitian/p/4822808.html#linux 之前看到朋友还动不动 apt-get update upgrade,就很纳闷 ...

  8. 升级PHPstudy自带的mysql版本 从5.5升级到5.7.22

    原文:升级PHPstudy自带的mysql版本 从5.5升级到5.7.22 版权声明:请注意:如需转载请注明出处. https://blog.csdn.net/qq_32534555/article/ ...

  9. ASP.NET 5 RC1 升级 ASP.NET Core 1.0 RC2 记录

    升级文档: Migrating from DNX to .NET Core Migrating from ASP.NET 5 RC1 to ASP.NET Core 1.0 RC2 Migrating ...

随机推荐

  1. ABP理论学习之启动配置

    返回总目录 本篇目录 配置ABP 配置模块 为模块创建配置 为了在应用启动时配置ABP和模块,ABP提供了一个基础设施. 配置ABP 配置ABP是在模块的PreInitialize事件中完成的.下面的 ...

  2. Prim 最小生成树算法

    Prim 算法是一种解决最小生成树问题(Minimum Spanning Tree)的算法.和 Kruskal 算法类似,Prim 算法的设计也是基于贪心算法(Greedy algorithm). P ...

  3. Hadoop学习笔记—10.Shuffle过程那点事儿

    一.回顾Reduce阶段三大步骤 在第四篇博文<初识MapReduce>中,我们认识了MapReduce的八大步骤,其中在Reduce阶段总共三个步骤,如下图所示: 其中,Step2.1就 ...

  4. ASP.NET MVC 5 Web编程2 -- URL映射(路由原理)

    本章将讲述ASP.NET MVC5 的路由原理,即URL映射机制. 简单点就是解释:为什么MVC在浏览器输入地址就能访问到类(或类中的方法)?这是怎么做到的?我自己可以通过.NET写出一个自己的MVC ...

  5. Android动画小记录

    今天在做一个头部滑动菜单的时候需要使用TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYD ...

  6. C#+OpenGL+FreeType显示3D文字(2) - 用GLSL+VBO绘制文字

    C#+OpenGL+FreeType显示3D文字(2) - 用GLSL+VBO绘制文字 +BIT祝威+悄悄在此留下版了个权的信息说: 上一篇得到了字形贴图及其位置字典(可导出为XML).本篇就利用此贴 ...

  7. IoC在ASP.NET Web API中的应用

    控制反转(Inversion of Control,IoC),简单地说,就是应用本身不负责依赖对象的创建和维护,而交给一个外部容器来负责.这样控制权就由应用转移到了外部IoC容器,控制权就实现了所谓的 ...

  8. 通过扩展让ASP.NET Web API支持W3C的CORS规范

    让ASP.NET Web API支持JSONP和W3C的CORS规范是解决"跨域资源共享"的两种途径,在<通过扩展让ASP.NET Web API支持JSONP>中我们 ...

  9. Git命令汇总

    1. 工作区和版本库 说明: 工作区(Working Directory)就是创建仓库的文件夹 版本库(Repository)就是工作区的隐藏目录.git,版本库中有暂存区(stage/index)和 ...

  10. 【Win10应用开发】通过拖放来打开文件

    除了可以使用XXXFilePicker来浏览文件外,其实在UWP APP中,也可以向传统Windows窗口一样,通过拖放的方式来打开文件. 处理过程和WPF的原理差不多,毕竟都是一脉相承,于是,在学习 ...