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. ASP.NET MVC项目实践技巧

    原创文章转载请注明出处:@协思, http://zeeman.cnblogs.com 在.NET开发初期,微软提供的WEB开发模型是WebForm,试图消除Web和桌面的隔阂,建立一致的开发体验.但是 ...

  2. 微冷的雨之Java中的多线程初理解(一)

    在讲解多线程前,我们必须理解什么是多线程?而且很多人都会将进程和线程做对比. 进程和线程 进程:进程是操作系统结构的基础,是一次程序的执行,是一个程序及其数据在处理机上顺序执行时所发生的活动,是程序在 ...

  3. YY一下微信线下支付的场景

    在上一篇文章里面提到了 <跨行清算的实现原理>,这次来分析一下线下支付的场景和流程. 今天看到一篇文章:http://www.huxiu.com/article/23248/1.html? ...

  4. C#实现二维码功能,winform 以及 asp.net均可以用

    二维码现在用途很多,怎么用C#编程生成呢? 准备 ThoughtWorks.QRCode.dll 需要 一个类 QRCode,这个类专门来生成二维码的 using System; using Syst ...

  5. 【深入浅出Linux网络编程】 "开篇 -- 知其然,知其所以然"

    [深入浅出Linux网络编程]是一个连载博客,内容源于本人的工作经验,旨在给读者提供靠谱高效的学习途径,不必在零散的互联网资源中浪费精力,快速的掌握Linux网络编程. 连载包含4篇,会陆续编写发出, ...

  6. Latch2:Latch和性能

    1,数据的IO操作 SQL Server访问的任何一个Page必须存在于内存中,如果不存在于内存中,那么SQL Server发出 Disk IO请求,将数据页从Disk读取到内存中,然后SQL Ser ...

  7. ajax局部刷新后,如何让局部中的百度分享重新加载

    我这个人不怎么喜欢说太多话,看几个图你们就懂了 Ajax前 Ajax之后 原因分析 解决方法 收工 百度分享是集成了众多主流第三方网站分享和收藏按钮的工具. 通过百度分享轻松将主流第三方网站的分享按钮 ...

  8. 简单生成svg文件

    this.fileSaveSync = function (file, data) { var fs = require('fs-extra'); fs.writeFileSync(file, dat ...

  9. Struts.xml中Action的method与路径的三种匹配方法

    原文  http://blog.csdn.net/woshixuye/article/details/7734482 首先我们有一个Action——UserAction public class Us ...

  10. 在.NET开发面向Oracle数据库的应用程序

    其实这个不是一个什么新的话题.但是之前在多次项目中,总是遇到大家针对Oracle数据库的访问时,会有各种各样的问题,最基本的就是要在客户端安装各种client,版本不一样的话还有各种问题. 静下心来看 ...