C# 如何处理WebAPI上的路由冲突-字符串ID与操作+;身份证件
我在.NET4上使用WebAPI托管RESTAPI(nuget上的WebAPI版本4.0.30506)。为了让属性路由更加复杂,我的解决方案中也包含了属性路由 我有两个属性路由冲突。冲突的原因是,我们在一个调用中通过字符串标识符进行查询,在另一个调用中通过字符串操作+数字标识符进行查询。HTTP响应中抛出的消息读取C# 如何处理WebAPI上的路由冲突-字符串ID与操作+;身份证件,c#,.net,asp.net-web-api,attributerouting,C#,.net,Asp.net Web Api,Attributerouting,我在.NET4上使用WebAPI托管RESTAPI(nuget上的WebAPI版本4.0.30506)。为了让属性路由更加复杂,我的解决方案中也包含了属性路由 我有两个属性路由冲突。冲突的原因是,我们在一个调用中通过字符串标识符进行查询,在另一个调用中通过字符串操作+数字标识符进行查询。HTTP响应中抛出的消息读取,找到了与请求匹配的多个操作。以下是示例查询以演示这两种查询: 1) http://example/api/libraries/?libraryId=some_library (som
,找到了与请求匹配的多个操作。以下是示例查询以演示这两种查询:
1) http://example/api/libraries/?libraryId=some_library (some_library is a string identifier)
2) http://example/api/libraries/bookStatus/1 (1 is the library database ID)
我一直在努力用不同的方法来实现这一目标。我当前的控制器签名如下所示:
[GET("api/libraries/?libraryId={libraryId}", Precedence = 2)]
[System.Web.Http.HttpGet]
public Library QueryLibraryByLibraryId(string libraryId){}
[GET("api/libraries/bookStatus/{libraryId:long}", Precedence = 1)]
[System.Web.Http.HttpGet]
public Dictionary<string, Dictionary<string, string>> QueryBookStatus(long libraryId){}
[GET(“api/libraries/?libraryId={libraryId}”,优先级=2]
[System.Web.Http.HttpGet]
公共库QueryLibraryByLibraryId(字符串库ID){}
[GET(“api/libraries/bookStatus/{libraryId:long}”,优先级=1)]
[System.Web.Http.HttpGet]
公共字典QueryBookStatus(长库ID){}
我可以理解为什么路由可能会混淆:如何知道“bookStatus/1”
的字符串标识符无效是一个很好的问题。然而,我认为这应该更容易定义一些约束
如何在维护这种类型的签名结构的同时解决这些冲突?问题在于,默认WebAPI路由约定在属性路由之前匹配
您应该将属性routing设置为默认路由,这意味着在WebApiConfig.cs中,
你需要打电话
config.Routes.maphttpAttribute路由
先打电话给其他人
config.Routes.MapHttpRoute
还有一件事是可选的,您不需要在第一个方法的查询部分中指定libraryId
它可以自动完成
[GET("api/libraries", Precedence = 2)]
[System.Web.Http.HttpGet]
public Library QueryLibraryByLibraryId(string libraryId) { }
[GET("api/libraries/bookStatus/{libraryId:long}", Precedence = 1)]
[System.Web.Http.HttpGet]
public Dictionary<string, Dictionary<string, string>> QueryBookStatus(long libraryId) { }
[GET(“api/库”,优先级=2)]
[System.Web.Http.HttpGet]
公共库QueryLibraryByLibraryId(字符串库ID){}
[GET(“api/libraries/bookStatus/{libraryId:long}”,优先级=1)]
[System.Web.Http.HttpGet]
公共字典QueryBookStatus(长库ID){}
问题在于默认WebAPI路由约定在属性路由之前匹配
您应该将属性routing设置为默认路由,这意味着在WebApiConfig.cs中,
你需要打电话
config.Routes.maphttpAttribute路由
先打电话给其他人
config.Routes.MapHttpRoute
还有一件事是可选的,您不需要在第一个方法的查询部分中指定libraryId
它可以自动完成
[GET("api/libraries", Precedence = 2)]
[System.Web.Http.HttpGet]
public Library QueryLibraryByLibraryId(string libraryId) { }
[GET("api/libraries/bookStatus/{libraryId:long}", Precedence = 1)]
[System.Web.Http.HttpGet]
public Dictionary<string, Dictionary<string, string>> QueryBookStatus(long libraryId) { }
[GET(“api/库”,优先级=2)]
[System.Web.Http.HttpGet]
公共库QueryLibraryByLibraryId(字符串库ID){}
[GET(“api/libraries/bookStatus/{libraryId:long}”,优先级=1)]
[System.Web.Http.HttpGet]
公共字典QueryBookStatus(长库ID){}
我已经用一个示例项目测试了您的配置。你似乎在以下某个方面犯了错误。我将简要介绍我所做的工作,请验证您是否也做了同样的工作-
One删除默认路由
默认情况下,ASP.NETMVC路由配置为使用默认值服务。这是我删除的第一件事,以确保我的属性路由正常工作我们可以稍后引入默认路由,但现在将其删除,以便它不会干扰。因此,请从WebApiConfig
class中删除以下内容或注释-
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
所以我的路线配置是这样的-
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//config.Routes.MapHttpRoute(
// name: "DefaultApi",
// routeTemplate: "api/{controller}/{id}",
// defaults: new { id = RouteParameter.Optional }
//);
// Uncomment the following line of code to enable query support for actions with an IQueryable or IQueryable<T> return type.
// To avoid processing unexpected or malicious queries, use the validation settings on QueryableAttribute to validate incoming queries.
// For more information, visit http://go.microsoft.com/fwlink/?LinkId=279712.
//config.EnableQuerySupport();
// To disable tracing in your application, please comment out or remove the following line of code
// For more information, refer to: http://www.asp.net/web-api
config.EnableSystemDiagnosticsTracing();
}
}
三个现在,由于我们在某些地方有路由,让我们的控制器方法执行测试-
namespace MvcApplication1.Controllers
{
public class ValuesController : ApiController
{
......
[GET("api/libraries", Precedence = 2)]
public string Get_1(string id)
{
return "value :" + id;
}
[GET("api/libraries/bookStatus/{id:long}", Precedence = 1)]
public string Get_2(int id)
{
return "value :" + id;
}
......
}
}
你猜怎么着?这两个url都有效-
/api/libraries/?id=2
/api/libraries/bookStatus/5
到现在为止,你已经有了解决方案。但让我们看看为什么会这样?如下所述-
原因
首先请注意,默认路由应该由控制器的名称提供服务,并且我的控制器的名称与使用的路径不对应,这是因为我想向您说明为什么会发生这种情况。由于我们的属性路由正在工作,所以我们正在为URL提供服务,即使我们的api控制器名称与路由不同。但默认路由无法做到这一点,因此会出现错误
首先让我们通过转到/api/{controller}/{id}
来验证我们的默认路由是否不起作用,因此我们浏览-/api/values/5
,它显示404。很明显是因为我们把它拿走了
让我们回到我们在One中删除的旧MVC默认路由
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
现在让我们再试一次,瞧!!。我们得到了错误:)-
我需要解释更多吗?:)。。。我想你知道原因了
但是等等。。。我们需要我们的默认路线,对吗?好的,然后在我们的属性路由之后注册它,这就是解决方案。。。在这一点上的所有工程-
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
//code to register attribtue routes
GlobalConfiguration.Configuration.Routes.MapHttpAttributeRoutes(config =>
{
config.AddRoutesFromAssembly(Assembly.GetExecutingAssembly());
});
//after attribute routes, now we can safely register our default routes
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
我已经用一个示例项目测试了您的配置。你似乎在以下某个方面犯了错误。我将简要介绍我所做的工作,请验证您是否也做了同样的工作-
One删除默认路由
默认情况下,ASP.NETMVC路由配置为使用默认值服务。这是我删除的第一件事,以确保我的属性路由正常工作我们可以稍后引入默认路由,但现在将其删除,以便它不会干扰。因此,请从WebApiConfig
class中删除以下内容或注释-
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
所以我的路线配置是这样的-
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//config.Routes.MapHttpRoute(
// name: "DefaultApi",
// routeTemplate: "api/{controller}/{id}",
// defaults: new { id = RouteParameter.Optional }
//);
// Uncomment the following line of code to enable query support for actions with an IQueryable or IQueryable<T> return type.
// To avoid processing unexpected or malicious queries, use the validation settings on QueryableAttribute to validate incoming queries.
// For more information, visit http://go.microsoft.com/fwlink/?LinkId=279712.
//config.EnableQuerySupport();
// To disable tracing in your application, please comment out or remove the following line of code
// For more information, refer to: http://www.asp.net/web-api
config.EnableSystemDiagnosticsTracing();
}
}
三个现在,由于我们在某些地方有路由,让我们的控制器方法执行测试-
namespace MvcApplication1.Controllers
{
public class ValuesController : ApiController
{
......
[GET("api/libraries", Precedence = 2)]
public string Get_1(string id)
{
return "value :" + id;
}
[GET("api/libraries/bookStatus/{id:long}", Precedence = 1)]
public string Get_2(int id)
{
return "value :" + id;
}
......
}
}
你猜怎么着?两者都是url