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}")]
.
我的问题与 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}")]
.