【问题标题】:What's the best way to change how Areas get created in Razor MVC?在 Razor MVC 中更改区域创建方式的最佳方法是什么?
【发布时间】:2015-04-02 18:03:39
【问题描述】:

我正在过渡到在项目中使用区域,每次我创建一个新区域时,我都必须更改一些内容以使其符合我希望的工作方式。更改涉及:

  • 删除创建的文件夹之一
  • 稍微修改 web.config 文件
  • 使用一些默认值添加一个或两个新文件
  • 稍微修改 AreaRegistration 文件

我宁愿每次创建新区域时都不必做这些相同的事情,因为我担心惯例会被遗忘并且会搞砸。有没有办法修改 New > Area 的默认值?或者也许可以制作一个新的文件模板来满足我的需求?

【问题讨论】:

  • 为什么要进行前两个更改?
  • 第一个更改只是因为我们更愿意遵循的约定(在 Controllers 文件夹之外有控制器,但这没什么大不了的,如果没有改变也不会介意)。需要进行 web.config 修改,因为默认包含 System.Web.Optimization,我们不使用它,因此忘记删除该行会破坏构建。

标签: c# asp.net-mvc asp.net-mvc-4 razor


【解决方案1】:

我正在过渡到在项目中使用区域

几个月以来我一直在做类似的事情,但从一个旧的 WebForms 项目开始,通过 VS 2013 的 Add -> New Scaffolded Item... 功能添加 MVC 组件,以便在服务器端利用 MVC 的结构和路由。我也一直在服务器端合并 WebAPI 和 SignalR。我绝对仍然是一个初学者,但在类似的过程中可能会走得更远一些,这里有一些关于你想要实现的想法和问题:


  • 删除创建的文件夹之一
  • 稍微修改 web.config 文件
  • 使用一些默认值添加一个或两个新文件

你在什么环境下开发?例如,如果您使用 VS 2013 的脚手架,您很可能会修改 T4 模板以防止或重定向文件夹、类等的创建。 Here 是一个帖子地址,您可以在其中找到这些模板,here 只是 T4 的众多介绍之一。您机器上模板的路径将根据 VS 版本而有所不同。通过修改或创建新模板,您应该能够相对容易地完成以上所有 3 点。如果您在这样的环境中工作,我将尝试详细说明您可能如何修改开箱即用的模板(可能已经有很多帖子可供您参考,但它们会做得更好)。


  • 稍微修改 AreaRegistration 文件

如果您使用的是 MVC 5 或更高版本,我建议您使用属性路由。在 API 范式中工作时,这似乎更标准(继承自 ApiController 而不是 Controller),但我发现将其扩展到传统的 MVC 控制器非常有用。

假设 MVC 5,我建议修改 AppStart\RouteConfig.csRegisterRoutes() 方法,以启用属性路由,然后添加一个包罗万象的路由,例如:

routes.MapMvcAttributeRoutes();

routes.MapRoute(
    "NotFound",
    "{*url}",
    new {
        controller = "Error",
        action = "Index"
    });

那时我会删除 xAreaRegistration.cs 文件,并从Global.asax 中删除对RegisterAllAreas() 的调用,但您不必走那么远。然后我根据需要用属性装饰我的控制器的类(无论它们住在哪里)和它们的方法。使用属性路由,我已经能够将自己从传统的 MVC 约定中解脱出来。我仍然可以使用它们,但我可以将控制器放置在项目中的任何位置,并轻松定义它们的动作路线。

话虽如此,您可能应该遵循一些类似路由组的组织标准,以便随着项目的发展,您不会发现自己浪费大量时间来搜索与某组路由匹配的所有控制器/动作。


这里有一个简单的例子来说明这实际上是如何从 URI 转换为方法调用的:

如果我有控制器ctl 和动作act逻辑上 区域ar,URI 为http://localhost/ar/ctl/a/1,将通过使用属性路由到下面的MyControllerNameDoesNotMatter.Index(1)装饰如:

[RouteArea("ar")]
[RoutePrefix("ctl")]
public class MyControllerNameDoesNotMatter : Controller {
    ...        
    [Route("a/{optionalParamDefaultsToNegativeOne=-1}")]
    public ActionResult Index(int optionalParamDefaultsToNegativeOne) {
        ...
    }
}

这种查看区域的方式比物理更符合逻辑,因为MyControllerNameDoesNotMatter.cs 文件不必位于Area\ar\Controllers 文件夹中。自从采用这一点后,我实际上已经不再使用 Area 脚手架,而是在非常高的层次上布置应用程序模块 - 想想可能是独立 SPA 的子应用程序。

我已尝试基于“catch-all”路由属性,并将其从RouteConfig.cs 中删除,但我未能成功完成此操作。问题是路由优先级。它可以很好地作为无效路线的包罗万象。但是对于有效路由,最终会匹配多 (2) 个路由,因为这两个属性路由具有相同的优先顺序。而在RouteConfig.cs 中定义的包罗万象,在注册所有属性路由后,属性路由优先。我发现了试图解决这个问题的混合答案。在某些时候,Route 属性似乎有一个NumberOrder 参数,但我没有运气。这似乎是一个悬而未决的问题。 Just one of many SO questions,没有得到答复。

编辑以考虑 mvc4 标记

在发布之前我没有看到 mvc4 标签。有一些可用的 nuget 包可以实现大部分相同的功能,例如用于早期版本的 MVC 的 scaffoldingattribute routing

【讨论】:

  • 这是一个非常详细的答案!我一定会尽快完成的!
猜你喜欢
  • 2018-02-01
  • 2018-07-16
  • 1970-01-01
  • 2017-08-06
  • 1970-01-01
  • 2011-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多