在 Razor MVC 中更改区域创建方式的最佳方式是什么?



我正在过渡到在项目中使用Areas,每次创建新的Areas时,我都必须更改一些内容,使其符合我希望的工作方式。这些变化包括:

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

我宁愿每次创建一个新区域时都不必做同样的事情,因为我担心大会会被遗忘,有些事情会变得一团糟。有没有办法修改"新建">"区域"的默认值?或者可以制作一个新的文件模板来满足我的需求吗?

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

几个月来,我一直在做类似的事情,但从一个旧的WebForms项目开始,通过VS2013的Add -> New Scaffolded Item...功能添加MVC组件,以便在服务器端利用MVC的结构和路由。我还在服务器端集成了WebAPI和SignalR。我肯定还是一个初学者,但在类似的过程中可能会走得更远,以下是我对你想要实现的目标的一些想法和问题:


  • 删除已创建的文件夹之一
  • 稍微修改web.config文件
  • 添加一两个具有某些默认值的新文件

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


  • 稍微修改AreaRegistration文件

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

假设MVC是5,我建议修改AppStartRouteConfig.csRegisterRoutes()方法,启用属性路由,然后添加一个catch-all路由,例如:

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文件不必在AreaarControllers文件夹中。自从采用这种方法以来,我实际上已经不再使用Area脚手架,而是在非常高的级别上布局应用程序模块——想想子应用程序,它可能是一个独立的SPA。

我曾尝试使"catch-all"路由属性基于,并将其从RouteConfig.cs中删除,但我未能成功做到这一点。问题在于路线优先级。它可以很好地作为无效路由的捕获。但对于一个有效的路由,多(2)个路由最终会匹配,因为这两个属性路由具有相同的优先级。然而,对于RouteConfig.cs中定义的catch-all,在注册所有属性路由之后,属性路由优先。在试图解决这个问题时,我发现了各种各样的答案。在某个时刻,Route属性似乎有一个NumberOrder参数,但我运气不好。这似乎是一个尚未解决的问题。这只是众多SO问题中的一个,这些问题尚未得到解答。

已编辑为mvc4标记的帐户

在发布之前,我没有看到mvc4标签。有一些nuget包可以实现大部分相同的功能,例如早期版本MVC的脚手架和属性路由。

最新更新