ASP.NET MVC路由的操作前缀

时间:2016-03-06 11:50:41

标签: asp.net-mvc asp.net-mvc-5 routes url-routing 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
}

这很好,期待我希望我的路由“看起来像”一个Type是嵌套的:

~/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路线,我不喜欢。

是否有某种方法可以“拦截”此路线并为操作添加“类型”前缀,以便它正确映射到控制器操作,但提供了一个干净的URL,我喜欢的方式?

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

(作为一般说明,我试图避免属性路由,因为我喜欢让我的所有路由定义来自一个地方而不是分散在各处)

3 个答案:

答案 0 :(得分:3)

您可以启用Fiddle

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) {...}
    // ...
}

答案 1 :(得分:1)

虽然密集,但有可能。你必须手动输入所有路线以获得你想要的东西,这将破坏达成惯例的目的。

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 }
);
//....

答案 2 :(得分:1)

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

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

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

  • /提供者/ {动作}
  • /提供者/类型/ {动作}

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