Web Api 路由:发现多个控制器类型与参数 VS 常量路径的 URL 匹配

Web Api Routing: Multiple controller types were found that match the URL for parameter VS constant paths

我的问题与 Web Api Routing : Multiple controller types were found that match the URL 类似,但我想将它们放在单独的控制器中。

根据评论,2 个预先存在的答案是很好的解决方法,但没有解决我试图解决的实际问题。

我编写的 URLs 类似于文件系统中的嵌套目录,或者与 Firebase URLs 非常相似。

/BiggestSet/{BiggestSetCode}/Subset1/{Subset1Code}/SubsetOfSubset1/{SubsetOfSubset1}

...等一直到树停止的地方。将其视为数据树。

/Collection/{Instance}/Collection/{Instance}

我遇到的问题是,在 /Collection 级别,我还想提供特定的集合级别操作。像添加和搜索以及其他特定于集合的操作 Collection/ProccessData

Collection Controller:
/Collection/Add 
/Collection/ProcessDataOnTheColleciton

Instance Controller:
/Collection/{InstanceCode}
/Collection/{InstanceCode}/ProcessOnTheInstance

我遇到的问题是 Collection/ProcessData 与实例 Collection/{InstanceCode} 冲突

注意:1为参数,1为常数。

如果您设置控制器以便集合和实例位于同一个控制器中。 /{InstanceCode} 与 /ProcessData

不冲突

但是

如果您将控制器拆分为逻辑函数,WebAPI 会给出错误 Multiple controller types were found that match the URL.

有谁知道如何修改属性路由,使其以某种方式表现得好像它们在同一个控制器中一样,或者在控制器之间优先考虑常量而不是参数?

要保留两个独立的控制器并仍然有这样的路由,您可以使用正则表达式路由约束。这样你就可以为 instanceCode 指定你接受除来自其他控制器的操作之外的所有内容。

下面是如何配置路由的示例:

public class CollectionController : ApiController
{
   [HttpGet]
   [Route("Collection/Add")]
   public string Add()
   {
      return $"CollectionController = Collection/Add";
   }

   [HttpGet]
   [Route("Collection/Process")]
   public string Process()
   {
      return $"CollectionController = Collection/Process";
   }
}

public class InstanceController : ApiController
{
   [HttpGet]
   [Route("Collection/{instanceCode:regex(^(?!Add$|Process$).*)}")]
   public string Get(string instanceCode)
   {
      return $"InstanceController = Collection/{instanceCode}";
   }

   [HttpGet]
   [Route("Collection/{instanceCode:regex(^(?!Add$|Process$).*)}/Process")]
   public string Process(string instanceCode)
   {
      return $"InstanceController = Collection/{instanceCode}/Process";
   }
}

这里还有一个link到示例中使用的post that explains the regular expression

如果您有特定格式的 instanceCode 并将正则表达式设置为仅接受此特定格式,则更好的选择是。这样您就不需要为添加的每个新操作修改正则表达式。我还包括一个 link 到 documentation for all available Route constraints。在那里你可以看到所有可用的选项。例如,如果您的实例代码是一个数字,您甚至不需要正则表达式,您可以像这样使用 int 约束进行限制 [Route("Collection/{instanceCode:int}")].