2017-09-22
refer :
https://msdn.microsoft.com/en-us/magazine/mt763233.aspx?f=255&MSPPError=-2147217396
https://scottsauber.com/2016/04/25/feature-folder-structure-in-asp-net-core/
https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/areas
典型的 MVC 结构是像上面这样的, 所有的 controllers, views 独立收藏.
这种结构在项目逐渐复杂后就会变得很难用.
这里介绍另一种结构
比如我们要开发一个 Web, 一个 AMP 版本, 还要公开一些 API.
那么我们可能希望结构像上面这样, 大伙分开管理, 但又可以用相同名字的控制器.
怎么实现呢 ?
首先要引入 Area 概念, 这个是 core 的新东西.
从前的 route 匹配只有 controller + action , 现在多了一个 area
namespace Project.Controllers
{
[Area("Web")]
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
}
每个控制器要定义好专属的 Area.
然后是 startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMvc(routes =>
{
routes.MapRoute(
name: "AMP",
template: "amp/{controller=Home}/{action=Index}",
defaults : new { area = "AMP" }
); routes.MapRoute(
name: "Web",
template: "{controller=Home}/{action=Index}",
defaults: new { area = "Web" }
);
});
}
Area 的部分说完了.
另一个重点是 Feature, feature 只是个代名词, 也不是 core 的东西.
它只是一个寻找 .cshtml 的方法而已.
core 原生的结构是这样的 : 路由匹配到控制器后, 通过 area + control + action 去 Views 里面寻找 cshtml
然而现在我们把 Views 给删除了, 所以我们得告诉它新的 location
在 startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.Configure<RazorViewEngineOptions>(options =>
{
options.ViewLocationExpanders.Add(new FeatureLocationExpander());
});
services.AddMvc();
}
设置新的 location 逻辑
public class FeatureLocationExpander : IViewLocationExpander
{
public void PopulateValues(ViewLocationExpanderContext context)
{
// Don't need anything here, but required by the interface
} public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
{
// {0} - Action Name
// {1} - Controller Name
// {2} - Area Name
return new string[] {
"/{2}/{1}/{0}.cshtml",
"/{2}/Shared/{0}.cshtml"
};
}
}
以上.