ASP.NET MVC 路由的操作前缀

Action Prefix to ASP.NET MVC Routing

我想设置一个路由,提交给带有前缀操作的控制器。

例如,我有一个 ProvidersController 服务提供商,我有一个 ProviderType 模型,我想在 Providers 控制器中处理(它是一个轻量级对象,我只是假设没有专门为这些小的支持对象中的每一个设置新的控制器,因此我想将它们分组到 Providers 控制器中。

因此,我的 ProvidersController 具有用于管理提供商的标准操作:

public class ProvidersController : ControllerBase
{
    public ActionResult Index() { }
    public ActionResult Create() { }
    public ActionResult Edit(int id) { }
    // ect ect
}

我也想在这里处理 ProviderTypes:

public class ProvidersController : ControllerBase
{
    public ActionResult Index() { }
    public ActionResult Create() { }
    public ActionResult Edit(int id) { }
    // ect ect
    public ActionResult TypeIndex() { }
    public ActionResult TypeCreate() { }
    public ActionResult TypeEdit(int id) { }
    // ect ect
}

一切都很好,希望我的路由到 "look like" 嵌套类型:

~/Providers/Create
~/Providers/Types/Create

这是我想到的路线:

routes.MapRoute(
    name: "ProviderTypes",
    url: "Providers/Types/{action}/{id}",
    defaults: new { controller = "Providers", action = "Index", id = UrlParameter.Optional }
);

但这需要我使用我不喜欢的 ~/Providers/Types/TypeCreate 路线。

有什么方法可以 "intercept" 这条路线并为动作添加 "Type" 前缀,以便它正确映射到控制器动作,但提供干净的 URL 我的方式喜欢吗?

例如,如何让 ~/Providers/Types/Create 映射到 ProvidersController.TypeCreate()

(一般来说,我试图避免属性路由,因为我希望所有路由定义都来自一个地方,而不是分散在各处)

您可以启用 ASP.NET MVC Attribute Routing

RouteConfig.cs

public static void RegisterRoutes(RouteCollection routes){
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    //enabling attribute routing
    routes.MapMvcAttributeRoutes();

    //You can also combine attribute routing with convention-based routing.
    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

然后在你的ProvidersController

[RoutePrefix("Providers"]
public class ProvidersController : ControllerBase {
    //eg: GET Providers
    [Route("")]
    public ActionResult Index() {...}
    //eg: GET Providers/Create
    [Route("Create")]
    public ActionResult Create() {...}
    //eg: GET Providers/Edit/5
    [Route("Edit/{id:int}")]
    public ActionResult Edit(int id) {...}
    // ...

    //eg: GET Providers/Types
    [Route("Types")]
    public ActionResult TypeIndex() {...}
    //eg: GET Providers/Types/Create
    [Route("Types/Create")]
    public ActionResult TypeCreate() {...}
    //eg: GET Providers/Types/Edit/5
    [Route("Types/Edit/{id:int}")]
    public ActionResult TypeEdit(int id) {...}
    // ...
}

虽然密集,但这是可能的。您必须手动输入所有路线才能获得所需的内容,这将违背约定的目的。

routes.MapRoute(
    name: "ProviderTypes",
    url: "Providers/Types",
    defaults: new { controller = "Providers", action = "TypeIndex" }
);

routes.MapRoute(
    name: "ProviderTypes_Create",
    url: "Providers/Types/Create",
    defaults: new { controller = "Providers", action = "TypeCreate" }
);

routes.MapRoute(
    name: "ProviderTypes_Edit",
    url: "Providers/Types/Edit/{id}",
    defaults: new { controller = "Providers", action = "TypeEdit", id = UrlParameter.Optional }
);
//....

一种选择是使用 MvcCodeRouting,实际上 将您的控制器嵌套到层次结构中。然后,您可以将 ProvidersTypes 分成逻辑嵌套的单独控制器。

> MyNamespace.Controllers.Providers.ProvidersController
    > MyNamespace.Controllers.Providers.TypesController

结果是获取基于您的控制器名称空间嵌套的 URL。

  • /供应商/{行动}
  • /Providers/Types/{动作}

有关详细信息,请参阅 Controllers and Namespaces