1

In my Web API scenario, this (default) route works well for almost all my controllers.

config.Routes.MapHttpRoute(
            name: "DefaultRoute",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

and for a couple of my controllers, I want to have them mapped by their action name, like this:

config.Routes.MapHttpRoute(
            name: "ActionRoute",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

Background:

Most of my controllers are to be mapped by default to GEE, POST, PUT and DELETE. However, I reserve some "admin" controllers that perform operations, such as data initialization, cleanup and testing stuff. These controllers may have multiple methods that are excetude via GET, hence the second route.

If I use either of these routes, they work well, however, if I set both, I get one of two failures:

Default route first:

api/books/                -> OK
api/books/someGuidId      -> OK
api/admin/someAdminAction -> 500 Internal Server Error (multiple actions found)
api/test/sometestAction   -> 500 Internal Server Error (multiple actions found)

Action route first:

api/books/                -> OK
api/books/someGuidId      -> 404 Not Found (no action that matches "someGuidId")
api/admin/someAdminAction -> OK
api/test/sometestAction   -> OK

My question is: how can I have these routes working out at the same time?

[EDIT]

api/books/someGuidId is not an important call, I can live without it (via GET) however, POST, PUT and DELETE to same url will fail, wich is not acceptable.

4

1 回答 1

3

路线的顺序很重要,因此您应该首先设置更具体的路线:

config.Routes.MapHttpRoute(
        name: "ActionRoute",
        routeTemplate: "api/{controller}/{action}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );

config.Routes.MapHttpRoute(
        name: "DefaultRoute",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );

编辑:

Default路线第一:

api/books/

此 url 匹配第一个模式:api/{controller}/{id}。
框架使用(PUT,POST,DELETE) 方法查找books控制器并找到它。GET使用默认值调用此方法id

api/admin/someAdminAction  

这个 url 也匹配第一个模式。(顺便说一句,在路由定义中如何命名参数并不重要:id或者superParamName,当框架将 URL 与路由进行比较时,它只会查找模式并且无法通过参数名称进行区分。

框架将尝试使用 id 调用控制器的GET(PUT,POST,DELETE) 方法(我想这不是有效的 id 值:)adminsomeAdminAction

Action当您首先定义路线时,您会得到类似的东西:

api/books/   

Matchs api/{controller}/{id}, id 可以省略,因为它被设置为“可选”。

api/books/someGuidId

匹配api/{controller}/{action}/{id},因此,当框架someGuidId在控制器中查找操作方法book但没有找到时,它会抛出异常。404 Not Found(没有匹配“someGuidId”的操作)

编辑 2: 我认为,如果您总是传递id“Actions”的参数并首先放置“Actions”路线,您将不会遇到任何冲突。尝试这个。
如果id在这两种情况下都需要参数是可选的,您可以将它从两个路由中删除并通过?(问号)以正常方式传递它。

其中之一将解决您的路由问题。

于 2013-09-02T18:23:19.357 回答