我在之前的项目中广泛使用过WCF。最近,我一直在探索使用ASP.NET Web API创建RESTful服务。在研究了REST服务的DO和DOT,甚至尝试了它之后,我有一个相当直截了当的问题。
假设我有一个UsersController
(继承ApiController
),我需要有3个GET类型的操作方法:
GetUsers()
GetUserById(string id)
GetUserByName(string name)
假设我在 WebApiConfig
中也有以下路线
config.Routes.MapHttpRoute(
name: "Users",
routeTemplate: "api/users/{id}",
defaults: new { controller = "users", id = RouteParameter.Optional }
);
http://localhost:<port>/api/users
显然会调用GetUsers()
当我需要调用带有单个参数的两个操作方法中的任何一个时,问题就出现了。
我想
http://localhost:<port>/api/users/5c6fe209-821e-475f-920d-1af0f3f52a82
调用GetUserById(string id)
和
http://localhost:<port>/api/users/jdoe
调用GetUserByName(string name)
我期望会发生的是,我会得到一个错误,或者只会调用第一个动作方法。
由于在消除歧义的路径上引入操作被视为偏离纯RESTful服务,如何使不同的URL调用相应的操作方法?我已经浏览了网页,大多数RESTful服务示例(由纯粹主义者)停在第一个操作方法来检索所有内容,而第二个操作方法则检索单个项目。
答案 0 :(得分:1)
这可以使用更具体的约束路线来实现。以下示例与您尝试实现的类似:
config.Routes.MapHttpRoute(
name: "ById",
routeTemplate: "api/{controller}/{id}",
defaults: new { action = "GetById" },
constraints: new { id = @"\d+" }
);
config.Routes.MapHttpRoute(
name: "ByName",
routeTemplate: "api/{controller}/{name}",
defaults: new { action = "GetByName", },
constraints: new { name = @"\w+" }
);
config.Routes.MapHttpRoute(
name: "All",
routeTemplate: "api/{controller}",
defaults: new { action = "GetAll", }
);
传递给MapHttpRoute的约束对象为不同的URL参数指定了正则表达式形式的约束。在此示例中,对于ById路由,我们仅在id参数为数字时才匹配。如果name参数是一个字母字符串,我们只匹配ByName。我们匹配所有没有参数。注意&#34; +&#34;在每个正则表达式上指定没有空值。路由按照定义的顺序进行匹配,因此您应该将最不具体的规则放在更具体的规则之下。
在您的情况下,您需要查找或编写与您正在使用的GUID格式匹配的正则表达式,并约束ById路由以匹配此表达式。然后,您需要在接受任何字符串的下方定义ByName路由。因为它在下面,只有在输入字符串不是GUID时才会被调用。
我还应该补充一点,如果您之前没有使用过MVC路由,那么它们就非常具体。您会注意到我的参数名称为ById的{id}和ByName的{name}。重要的是,这些参数与控制器方法上输入参数的确切名称相匹配,因为路由器使用此参数构建方法调用。即使您在操作上只有一个参数,如果名称未正确映射,您也会收到错误。