【发布时间】:2020-02-26 05:42:07
【问题描述】:
我正在开发一个基于 ASP.NET 的 .NET 4.6.1 Web 应用程序。我们的 Web API 控制器大量使用了[HttpGet] 和[HttpPost] 属性;路由是通过[Route] 属性完成的。
我了解,如果多个方法具有相同的路由,ASP.NET 将通过参数名称(和编号)来区分它们。
现在,在我的一个控制器上,我想提供一种方法(其路由,或至少路由 + HTTP 动词组合是唯一的),它将接受其查询字符串中的任何参数。最好,我想将解析后的查询字符串作为键/值对的列表,但如果我必须自己解析查询字符串,那也可以。
我怎样才能做到这一点,同时保持我们的通用代码结构(即依赖[Route] 进行路由等)?
我找到了几个可能的解决方案,但不知何故,总是缺少一些东西,或者至少,由于缺乏文档,我的发现是不确定的。例如:
- 我知道我可能可以通过
HttpContext访问完整的查询字符串,但这并不能解决 ASP.NET 必须首先将带有任意参数的请求映射到我的方法的路由问题。 - 我发现了一些关于模型绑定器的提示,但是从几个月前我实现模型绑定器时开始,它们似乎总是一次只能处理一个参数,而不是整个查询字符串中的所有参数。 (或者也许我弄错了,迷失在提供的物品的迷宫中?)
- 我曾尝试使用
DictionaryModelBinder<string, string>,但我从中得到的只是一个空的Dictionary<string, string>。
编辑:例如,我希望我的端点(我们称之为call)对以下任何一个做出反应:
.../call
.../call?a=5&b=20&c=800
.../call?a=foo&z=bar
简要原理:该方法位于我的实际控制器的抽象基类上。可以很容易地从运行时数据/反射中提取每个单独的控制器实际接受哪些 URL 参数的信息,因此如果收到的参数不合适,我可以自己返回状态 404。我不想要做的是为每个控制器单独实现该方法 - 即使这会让我在每个控制器上指定不同的参数,它也会造成不方便的冗余。
EDIT2:这是控制器外观的简化版本:
基类:
public abstract class ControllerBase<T, TKey> : ApiControllerBase
{
[Route("call")]
[HttpGet]
public T Call([FromUri(Name = "")] TKey key)
{
// retrieve T from database based on key (for instance)
}
}
还有一个实际控制人:
public class Thing
{}
public class ThingKey
{
public int OwnerId { get; set; }
public int Id { get; set; }
}
[RoutePrefix("api/thing")]
public class ThingController : ControllerBase<Thing, ThingKey>
{}
还有另一个控制器:
public class Stuff
{}
public class StuffKey
{
public int Scope { get; set; }
public int Group { get; set; }
public int UniqueKey { get; set; }
}
[RoutePrefix("api/stuff")]
public class StuffController : ControllerBase<Stuff, StuffKey>
{}
从这里可以看出,我的call 端点当前仍将参数从其 URL 查询字符串映射到控制器特定对象的属性。我想取消为每个控制器提供单独的键类的必要性,而是在字典或类似文件中接收call 的参数。
【问题讨论】:
-
您介意粘贴您的控制器代码吗?你有类似 Call([FromQuery] queryParam) 的东西吗?你在使用 .Net Core 吗? docs.microsoft.com/en-us/aspnet/core/web-api/…
-
@ZeinSleiman:我已更新问题以包含一些示例代码。
标签: asp.net .net asp.net-web-api routes query-string