我希望有两个不同的GET操作来查询数据,名称和ID,
我有这些路线:
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "ActionApiByName",
routeTemplate: "api/{controller}/{action}/{name}",
defaults: new { name = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
以及控制器中的这些操作:
[HttpGet]
public CompanyModel CompanyId(Guid id)
{
//Do something
}
[HttpGet]
public CompanyModel CompanyName(string name)
{
//Do something
}
这样的调用:http://localhost:51119/api/companies/CompanyId/3cd97fbc-524e-47cd-836c-d709e94c5e1e
可以运行并进入'CompanyId'方法,
对http://localhost:51119/api/companies/CompanyName/something
的类似调用让我找不到404
但是这个:
'http://localhost:51119/api/companies/CompanyName/?name=something
'工作正常
任何人都可以解释这种行为吗?我做错了什么?
答案 0 :(得分:10)
Web API路由选择器无法知道URL末尾的字符串是否为GUID。因此,不是为适当的GET操作选择正确的路线。
为了选择正确的路线,您需要为GUID uri模板添加路线约束。
public class GuidConstraint : IHttpRouteConstraint
{
public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values,
HttpRouteDirection routeDirection)
{
if (values.ContainsKey(parameterName))
{
string stringValue = values[parameterName] as string;
if (!string.IsNullOrEmpty(stringValue))
{
Guid guidValue;
return Guid.TryParse(stringValue, out guidValue) && (guidValue != Guid.Empty);
}
}
return false;
}
}
然后,将约束添加到将处理GUID的路由。
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional },
constraints: new { id = new GuidConstraint() } // Added
);
由于此路由比一般的“字符串”路由更具体,因此需要将其放置在要解析名称的路径上方。
这应该适当地路由到行动。
希望这有帮助。