使用区域和控制器名称进行路由(asp.net 核心)
Routing with Areas and Controller Name (asp.net core)
为了防止我的应用程序变得混乱,我开始使用区域。但是现在我总是要打电话:
http://localhost:49358/Document/Document/
而不是:
http://localhost:49358/Document/
如何更改我的路线以按区域名称访问控制器?
(没有家庭控制器)
我的项目中有以下文件夹结构:
我通往区域的路线代码如下所示:
routes.MapRoute(name: "areaRoute",template: "{area:exists}/{controller=Home}/{action=Index}");
然后我在我的 DocumentController 中放置了 [Area("Document")] 标签。
编辑:
正如 Shyju 和 Jamie Taylor 所建议的那样,我选择了 HomeControllers。 (感谢你们的快速回答和解释)
我的结构现在看起来像这样并且路由按预期工作:
对我来说,拥有这么多的 HomeControllers 和 Index Files 还是有点失望。浏览代码不再那么容易了:
编辑2:
在对所有这些 Homecontrollers 感到非常恼火之后,我采用了 Jamie Taylor 建议的解决方案,并将所有内容重新排列在 Features 文件夹中。它需要更多的配置,但在我看来更干净。
这篇微软文章中也有进一步的解释(只是跳过区域的东西):
https://msdn.microsoft.com/en-us/magazine/mt763233.aspx
我的结构现在看起来像这样,路由工作起来很有魅力,控制器名称仍然有意义:
区域的默认路由注册使用HomeController
作为url中控制器的默认值。如果您希望 DocumentController 成为默认值,请在 StatrtUp class.
中更新它
app.UseMvc(routes =>
{
routes.MapRoute(
name: "areas",
template: "{area:exists}/{controller=Document}/{action=Index}/{id?}"
);
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
请记住,该注册码适用于 所有 现有区域(因为我们在 url 模板中有 {area:exists}
),不只是文档区。这意味着,任何时候像 yourApp\someAreaName
这样的请求,框架都会将请求发送到 someAreaName
中 DocumentController
的索引操作。
您已经将与文档相关的代码组织到文档区域。现在为什么你需要你的控制器名称是 document ?我觉得,这是重复的。
我个人会把Document区里面的DocumentController
重命名为HomeController
并使用默认的路由注册码进行区注册(在[=34中使用HomeController作为默认控制器值) =] 模板)。这样,它将适用于您未来的领域,并且您的代码看起来更干净。 恕我直言,任何区域的 HomeController 都有意义,而任何区域的 DocumentController 都会令人困惑。
app.UseMvc(routes =>
{
routes.MapRoute(
name: "areas",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
);
});
我不确定这就是区域的用途。也许您应该重新考虑您的架构。
在我的 ASP.NET MVC Core application template 中,我利用了功能文件夹,它的工作原理有点像区域。
为此,我在 ConfigureServices
方法中添加了以下内容:
serviceCollection.Configure<RazorViewEngineOptions>(options =>
{
options.ViewLocationExpanders.Add(new FeatureLocationExpander());
});
其中 FeatureLocationExpander
是:
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)
{
// The old locations are /Views/{1}/{0}.cshtml and /Views/Shared/{0}.cshtml
// where {1} is the controller and {0} is the name of the View
// Replace /Views with /Features
return new string[]
{
"/Api/{1}/{0}.cshtml",
"/Features/{1}/{0}.cshtml",
"/Features/Shared/{0}.cshtml"
};
}
}
替换由 ExpandViewLocations
为您的区域返回的新字符串[] 的内容将意味着您不必添加路由属性。
但是,这不能解决您的问题,因为这不是区域的用途。
除非您在 Documents
区域下添加了一个 razor 页面(名为 Index.cshtml)作为文档区域的索引页面。此 Index.cshtml 可以在您的 /Documents/Documents/Index.cshtml 中提供 Index.cshtml 的所有功能,并具有代码隐藏式文件的额外好处(还记得 ASP.NET 网络表单吗?)它就像你的控制器。
为了防止我的应用程序变得混乱,我开始使用区域。但是现在我总是要打电话:
http://localhost:49358/Document/Document/
而不是:
http://localhost:49358/Document/
如何更改我的路线以按区域名称访问控制器?
(没有家庭控制器)
我的项目中有以下文件夹结构:
我通往区域的路线代码如下所示:
routes.MapRoute(name: "areaRoute",template: "{area:exists}/{controller=Home}/{action=Index}");
然后我在我的 DocumentController 中放置了 [Area("Document")] 标签。
编辑:
正如 Shyju 和 Jamie Taylor 所建议的那样,我选择了 HomeControllers。 (感谢你们的快速回答和解释)
我的结构现在看起来像这样并且路由按预期工作:
对我来说,拥有这么多的 HomeControllers 和 Index Files 还是有点失望。浏览代码不再那么容易了:
编辑2:
在对所有这些 Homecontrollers 感到非常恼火之后,我采用了 Jamie Taylor 建议的解决方案,并将所有内容重新排列在 Features 文件夹中。它需要更多的配置,但在我看来更干净。
这篇微软文章中也有进一步的解释(只是跳过区域的东西):
https://msdn.microsoft.com/en-us/magazine/mt763233.aspx
我的结构现在看起来像这样,路由工作起来很有魅力,控制器名称仍然有意义:
区域的默认路由注册使用HomeController
作为url中控制器的默认值。如果您希望 DocumentController 成为默认值,请在 StatrtUp class.
app.UseMvc(routes =>
{
routes.MapRoute(
name: "areas",
template: "{area:exists}/{controller=Document}/{action=Index}/{id?}"
);
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
请记住,该注册码适用于 所有 现有区域(因为我们在 url 模板中有 {area:exists}
),不只是文档区。这意味着,任何时候像 yourApp\someAreaName
这样的请求,框架都会将请求发送到 someAreaName
中 DocumentController
的索引操作。
您已经将与文档相关的代码组织到文档区域。现在为什么你需要你的控制器名称是 document ?我觉得,这是重复的。
我个人会把Document区里面的DocumentController
重命名为HomeController
并使用默认的路由注册码进行区注册(在[=34中使用HomeController作为默认控制器值) =] 模板)。这样,它将适用于您未来的领域,并且您的代码看起来更干净。 恕我直言,任何区域的 HomeController 都有意义,而任何区域的 DocumentController 都会令人困惑。
app.UseMvc(routes =>
{
routes.MapRoute(
name: "areas",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
);
});
我不确定这就是区域的用途。也许您应该重新考虑您的架构。
在我的 ASP.NET MVC Core application template 中,我利用了功能文件夹,它的工作原理有点像区域。
为此,我在 ConfigureServices
方法中添加了以下内容:
serviceCollection.Configure<RazorViewEngineOptions>(options =>
{
options.ViewLocationExpanders.Add(new FeatureLocationExpander());
});
其中 FeatureLocationExpander
是:
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)
{
// The old locations are /Views/{1}/{0}.cshtml and /Views/Shared/{0}.cshtml
// where {1} is the controller and {0} is the name of the View
// Replace /Views with /Features
return new string[]
{
"/Api/{1}/{0}.cshtml",
"/Features/{1}/{0}.cshtml",
"/Features/Shared/{0}.cshtml"
};
}
}
替换由 ExpandViewLocations
为您的区域返回的新字符串[] 的内容将意味着您不必添加路由属性。
但是,这不能解决您的问题,因为这不是区域的用途。
除非您在 Documents
区域下添加了一个 razor 页面(名为 Index.cshtml)作为文档区域的索引页面。此 Index.cshtml 可以在您的 /Documents/Documents/Index.cshtml 中提供 Index.cshtml 的所有功能,并具有代码隐藏式文件的额外好处(还记得 ASP.NET 网络表单吗?)它就像你的控制器。