C# 如何处理WebAPI上的路由冲突-字符串ID与操作+;身份证件

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

我在.NET4上使用WebAPI托管RESTAPI(nuget上的WebAPI版本4.0.30506)。为了让属性路由更加复杂,我的解决方案中也包含了属性路由

我有两个属性路由冲突。冲突的原因是,我们在一个调用中通过字符串标识符进行查询,在另一个调用中通过字符串操作+数字标识符进行查询。HTTP响应中抛出的消息读取
,找到了与请求匹配的多个操作。以下是示例查询以演示这两种查询:

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