【问题标题】:Routing with Areas and Controller Name (asp.net core)带有区域和控制器名称的路由 (asp.net core)
【发布时间】:2017-10-12 12:32:09
【问题描述】:

为了防止我的应用程序变得混乱,我开始使用区域。但现在我总是要打电话给:
http://localhost:49358/Document/Document/
而不是:
http://localhost:49358/Document/
如何更改我的路线以通过区域名称访问控制器? (没有 HomeController)

我的项目中有以下文件夹结构:


我的区域路线的代码如下所示:

routes.MapRoute(name: "areaRoute",template: "{area:exists}/{controller=Home}/{action=Index}");

然后我将 [Area("Document")] 标签放在 DocumentController 中。

编辑:
根据 Shyju 和 Jamie Taylor 的建议,我选择了 HomeControllers。 (谢谢你们的快速回答和解释)

我的结构现在看起来像这样,并且路由按预期工作:

对我来说,拥有如此多的 HomeController 和索引文件仍然有点令人失望。导航代码不再那么容易了:

编辑2:
在对所有这些 Homecontrollers 感到厌烦之后,我采用了 Jamie Taylor 建议的解决方案,并将所有内容重新排列在 Features 文件夹中。它需要更多的配置,但我认为它更干净。
在这篇微软文章中也有进一步的解释(跳过区域的东西):
https://msdn.microsoft.com/en-us/magazine/mt763233.aspx

我的结构现在看起来像这样,路由就像一个魅力,控制器名称仍然有意义:

【问题讨论】:

  • 我不确定这就是区域的用途。也许你应该重新考虑你的架构。也许您可以在文档区域下添加一个剃须刀页面,它的作用类似于索引页面并提供文档索引视图的所有功能
  • “区域是一种 ASP.NET MVC 功能,用于将相关功能组织到一个组中,作为单独的命名空间(用于路由)和文件夹结构(用于视图)”对我来说听起来很有希望。否则你会推荐什么?
  • 您在我的编辑完成之前到达那里:P

标签: c# .net asp.net-core asp.net-core-mvc asp.net-routing


【解决方案1】:

我不确定这就是区域的用途。也许你应该重新考虑你的架构。

在我的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 区域下添加了一个剃须刀页面(名为 Index.cshtml),它充当文档区域的索引页面。这个 Index.cshtml 可以在 /Documents/Documents/Index.cshtml 中提供 Index.cshtml 的所有功能,另外还有一个类似代码隐藏的文件(还记得 ASP.NET 网络表单吗?),它就像你的控制器.

【讨论】:

【解决方案2】:

区域的默认路由注册使用HomeController作为url中控制器的默认值。如果您希望 DocumentController 成为默认值,请在 StatrtUp 类中对其进行更新。

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 这样的请求,框架都会将请求发送到someAreaNameDocumentController 的索引操作。

您已经将与文档相关的代码组织到了文档区域。现在为什么你需要你的控制器名称是文档?我觉得,是重复的。

我会亲自将 Document 区域内的 DocumentController 重命名为 HomeController 并使用默认路由注册码进行区域注册(它使用 HomeController 作为 url 模板中的默认控制器值)。这样,它将适用于您未来的领域,并且您的代码看起来更干净。 恕我直言,任何领域的 HomeController 都有意义,但任何领域的 DocumentController 都会令人困惑。

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "areas",
        template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
    );
});

【讨论】:

  • 非常感谢您的回复。我也偶然发现了这种方法。但这意味着对于每个新的“模块”,startup.cs 中都会有一个新条目。我正在尝试实现类似:{area:exists}/{controller=}/{action=Index}/{id?}
  • 是的。这就是为什么我建议将您的控制器从 Document 重命名为 Home(您已经将代码组织到 Document 区域,为什么现在在控制器中重复名称?)并使用适用于您创建的所有新区域的默认(通用)注册代码将来。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-04
相关资源
最近更新 更多