Asp.Net Mvc里有一个叫做Area的技术,就是可以把不同逻辑组件的controller, view等放到不同的文件夹里。比如所有管理相关的都放到Admin area里。其实之前我一直对这个功能不太感冒,并不觉得能解决什么大问题,如果项目规模较大的话,肯定是很多开发协同开发,这时候很大的一个问题是版本库冲突的问题以及一个模块build不过导致其他模块受难。我觉得area并不能解决这个问题,直到我看到了Orchard的源码。

Orchard的思路简单来说就是,在Areas文件夹下建了好几个web工程,因为web工程下面会有Controllers, Views的文件夹结构,是完全符合area的结构定义的,然后把这个Areas文件夹从web project里exclude出去,在工程里就看不到了,最后再把这些工程加到solution里。这样不同模块的开发可以创建多个solution,每个solution里只引用自己所需的最少的工程就可以,避免了版本库冲突以及build失败的问题了。

当初我看到这种做法的时候不由得眼前一亮,这种结构可以很好地解决协同开发的问题,而且实现组件化,热插拔也都方便了许多。所以当开始学习Asp.Net 5(area实际上是Mvc的概念,说Mvc 6更严谨)的时候,一开始就想到了试试新框架的area功能。结果发现和以前的版本并不太一样。这里不做比较了,直接上代码。

首先在web工程里创建出Areas文件夹以及相应的结构目录

-Areas

--Management

---Controllers

----HomeController.cs

--Views

---_ViewStart.cshtml

---Home

----Index.cshtml

HomeController的Index action直接return View();, _ViewStart.cshtml是指定layout的,和web工程里的一样,当然你可以自己定义新的模板,自己可以添加_GlobalImport.cshtml以加入TagHelper和命名空间之类的,不多说。

真正的工作有两样,一是设置路由,二是标记Area。目前没发现MVC5里的area自动发现功能,所以需要给area的controller加上Area标签。

[Area("Management")]
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}

然后在web工程的Startup里添加路由。

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory)
{
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapRoute(
name: "area",
template: "{area:exists}/{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" });
});
}

启动项目,浏览器里输入url localhost:8888/Management就看到这个Management area的home页面了。

然后问题来了,我们写代码的时候,很多情况下都需要做一些自定义的东西,下面来看一下一些自定义的方法,主要处理三个问题:1,文件夹名不叫Areas,而是叫modules;2,不在Controller上加Area标签,自动发现;3,url里不包含area的名字。

第一个问题很好解决,就是告诉Razor引擎寻找View的时候别在Areas文件夹下找就可以了。实现一个自定义的RazorViewEngine,然后改变一下默认的搜索路径。别忘了把之前的Areas文件夹改名为modules。

public class CustomLocationRazorViewEngine : RazorViewEngine
{
public CustomLocationRazorViewEngine(IRazorPageFactory pageFactory, IRazorViewFactory viewFactory, IViewLocationExpanderProvider viewLocationExpanderProvider, IViewLocationCache viewLocationCache)
: base(pageFactory, viewFactory, viewLocationExpanderProvider, viewLocationCache)
{
var areaViewLocationFormats = AreaViewLocationFormats as string[];
areaViewLocationFormats[0] = "/modules/{2}/Views/{1}/{0}.cshtml";
areaViewLocationFormats[1] = "/modules/{2}/Views/Shared/{0}.cshtml";
}
}

第三个问题也比较好解决,只要在制定路由规则的时候,把area信息传一下就行了。

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapRoute(
name: "area",
template: "manage/{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index", area = "Management" });
});

第二个问题略微麻烦一点,什么样的Controller才是area里的Controller呢?即便能判定出这样的Controller来,又把它算到哪个area下面去呢?这个其实各个项目都有不同的需求,这里就假设,主web工程里的Controller的namespace都是AspNetAreaDemo.Controllers,除了这种命名空间的,都是area里的Controller,而area名字也通过namespace来体现。就是默认area Controller的命名空间都是XXX.XXX.XXX.AreaName.Controllers,这样用.分割一下,取倒数第二个就可以了。实际开发中,可能会以assembly的name,project的name等来作为area name,甚至干脆维护一个映射。

现在策略有了,怎么才能自动地给Controller加上Area标签呢。看看源码,AreaAttribute实际上是IRouteConstraintProvider接口的一个实现类,而这个接口是在ControllerModel类里有所体现的,是一个集合。所以我们需要做的就是给符合条件的ControllerModelRouteConstraints集合里添加一个AreaAttribute。代码如下

public class AreaAutoDiscoverControllerModelConvention : IControllerModelConvention
{
public void Apply(ControllerModel controller)
{
var ns = controller.ControllerType.Namespace;
if (ns != "AspNetAreaDemo.Controllers")
{
var segments = ns.Split(new char[] { '.' });
var areaName = segments[segments.Length - 2];
controller.RouteConstraints.Add(new AreaAttribute(areaName));
}
}
}

准备工作做完了,最后只要把自定义的RazorViewEngine和ControlleModelConvention添加到程序里就可以了。还是Startup类。

public void ConfigureServices(IServiceCollection services)
{
services.Configure<AppSettings>(Configuration.GetSubKey("AppSettings"));
services.AddMvc();
services.ConfigureMvc(options =>
{
options.ViewEngines.Clear();
options.ViewEngines.Add(new ViewEngineDescriptor(typeof(CustomLocationRazorViewEngine)));
options.Conventions.Add(new AreaAutoDiscoverControllerModelConvention());
});
}

启动程序,输入url localhost:8888/manage就看到新的页面了。

Asp.Net 5使用Area及自定义Area的更多相关文章

  1. [ASP.NET MVC 小牛之路]08 - Area 使用

    ASP.NET MVC允许使用 Area(区域)来组织Web应用程序,每个Area代表应用程序的不同功能模块.这对于大的工程非常有用,Area 使每个功能模块都有各自的文件夹,文件夹中有自己的Cont ...

  2. MVC自定义过滤器,自定义Area过滤器,自定义Controller,Action甚至是ViewData过滤器

    实现MVC自定义过滤器,自定义Area过滤器,自定义Controller,Action甚至是ViewData过滤器 MVC开发中几种以AOP方式实现的Filters是非常好用的,默认情况下,我们通过A ...

  3. 【ASP.NET MVC 学习笔记】- 09 Area的使用

    本文参考:http://www.cnblogs.com/willick/p/3331519.html 1.ASP.NET MVC允许使用 Area(区域)来组织Web应用程序,这对于大的工程非常有用, ...

  4. 把某个asp.net 控件 替换成 自定义的控件

    功能:可以把某个asp.net 控件 替换成 自定义的控件 pages 的 tagMapping 元素(ASP.NET 设置架构) 定义一个标记类型的集合,这些标记类型在编译时重新映射为其他标记类型. ...

  5. asp.net core参数保护之自定义要保护的参数类型

    asp.net core参数保护之自定义要保护的参数类型 Intro 为了实现 asp.net core 下的参数保护,扩展了asp.net core 中 DataProtection,可以自动化的保 ...

  6. ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET MVC 学习笔记-6.异步控制器 ASP.NET MVC 学习笔记-5.Controller与View的数据传递 ASP.NET MVC 学习笔记-4.ASP.NET MVC中Ajax的应用 ASP.NET MVC 学习笔记-3.面向对象设计原则

    ASP.NET MVC 学习笔记-7.自定义配置信息   ASP.NET程序中的web.config文件中,在appSettings这个配置节中能够保存一些配置,比如, 1 <appSettin ...

  7. 新西兰程序员 ASP.NET网站中设置404自定义错误页面

    新西兰程序员 ASP.NET网站中设置404自定义错误页面 在用ASP.NET WebForm开发一个网站时,需要自定义404错误页面. 做法是这样的 在网站根目录下建立了一个404.html的错误页 ...

  8. ASP.NET MVC Area使用-将Area设置成独立项目

    环境说明:Vistual Studio 2013 MVC 4.0 其实关于ASP.NET MVC Area使用的基础知识可以参考 http://www.cnblogs.com/willick/p/33 ...

  9. ASP.NET Core MVC 之区域(Area)

    区域(Area)是一个 ASP.NET MVC 功能,用于将相关功能组织为一个单独的命名空间(用于路由)和文件结构(用于视图).使用区域通过向控制器和操作添加 一个路由参数(area)来创建用于路由目 ...

随机推荐

  1. 通过autofac教你彻底明白依赖解耦(二)理论结合实践 - 大侠.Net

    上节说了一下基本的理论知识,例子可能不太好,不过无所谓了,目的是要让大家明白啥是依赖倒置和依赖注入,目的就达到了,简单一句话,这2玩意都是用来解耦合的. 不过依赖倒置这个词哥哥真不敢苟同,哥哥来个颠覆 ...

  2. 上传文件出错:org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. Stream ended unexpectedly

    最近做一个web项目中有上传文件的功能,已经写出并在本地和部署到服务器上测试了好几个文件上传都没问题(我用的是tomcat).后来又上传了一个700多K的文件(前边的都是不足600K的,并且这个wor ...

  3. ExpectationMaximum

    2- You may have question marks in your head, especially regarding where the probabilities in the Exp ...

  4. SQL Server 2005如何远程连接数据库?

    SQL Server 2005如何远程连接数据库? 方法/步骤   1 在配置工具中的服务和远程连接的外围应用配置器 --->远程连接-->本地连接和远程连接-->同时使用TCP/I ...

  5. 国外程序员整理的Java资源

    好资料,慢慢学习.http://www.importnew.com/14429.html 构建 这里搜集了用来构建应用程序的工具. Apache Maven:Maven使用声明进行构建并进行依赖管理, ...

  6. 洛谷 P1156 垃圾陷阱

    2016-05-31 09:54:03 题目链接 :洛谷 P1156 垃圾陷阱 题目大意: 奶牛掉坑里了,给定坑的深度和方块的个数,每个方块都可以垫脚或者吃掉维持生命(初始为10) 若可以出来,求奶牛 ...

  7. Turn Your Raspberry Pi Into a WiFi Hotspot with Edimax Nano USB EW-7811Un (RTL8188CUS chipset)

    http://www.daveconroy.com/turn-your-raspberry-pi-into-a-wifi-hotspot-with-edimax-nano-usb-ew-7811un- ...

  8. Apache Hadoop压缩包与Eclipse结合,导入jar包归整总结(手动)

    *************************  有些,是没必要全导入的.以后到工作了,用Maven,就自动会导入其中一些.************************ 一般,工作中,用的更多 ...

  9. Java & XML Tutorial

    Java comes with a set of tools to process XML. These Java XML tools are: SAX Parser StAX Parser DOM ...

  10. MSSQLSERVER数据库- 作业调度定时备份数据库

    作业调度和备份数据库是常见的行为,掌握这两项技术我觉的非常有必要. 在网上找到这个示例,记录在这里 备份数据库的SQL语句 --自动备份并保存最近5天的SQL数据库作业脚本 ) DECLARE @da ...