c# - 如何通过 Refit 和其他来源在 Web API 应用程序中将字典作为查询参数传递?
问题描述
我在将 Dictionary 作为父对象的一部分作为查询参数传递时遇到了一点问题。
所以,我有一个获取 FormulationParameters 变量的方法。
public async ValueTask<IActionResult> Get([FromQuery] FormulationParameters formulationParameters)
{
return Ok(await _service.Get(formulationParameters));
}
FormulationParameters 类如下所示:
public class FormulationParameters
{
//other simple properties, e.g. string, int
public Dictionary<string, string> Substitute { get; set; }
}
当我使用 Postman 传递这些参数时,我像这样填写了“查询参数”表单,一切正常:
- 我传递了一个 Key 作为Substitute[FirstValue],它的值为10
在Substitute字典中,我得到了 Key 等于"FirstValue"且其值为10的记录。
但是当我尝试通过 Refit 为我的 API 编写一些测试时,我发现这并没有像我预期的那样工作。
所以,我在 Refit 接口中有一个方法:
[Get("/api/path")]
Task<HttpResponseMessage> GetFormulations([Query] FormulationParameters parameters]
我在代码中填写了 FormulationParameters 的所有属性。当我调试我的测试时,我看到在 API 方法(上面定义)中,除了这个 Substitute 字典之外, formationParameters变量的所有属性都被填充了。
我在互联网上寻找这个问题并找到了一些解决方案。我都试过了,但对我没有用。
首先,我尝试为此属性使用[JsonDataExtension]属性。正如我所读到的,这意味着如果您将此属性用于某些属性,则 Request 中没有匹配类成员的所有参数都将写入指定的集合中。因此,我将Dictionary<string, string>更改为Dictionary<string, object>。此外,我更改了通过 Refit 方法发送数据的方式:我将 Substitute 从主类中移出并将其作为单独的参数发送,因此查询字符串如下所示:
?Codes=Code1,Code2&Type=Type&Language=en&FirstValue=1&SecondValue=10
但是,没有任何效果,Substitute仍然没有被填充。
另外,我尝试为这个属性编写一个自定义转换器,但没有效果,它甚至在请求到来时都没有调用。
起作用的一件事是动作过滤器。我在讨论相同问题的 StackOverflow 帖子中找到了这个解决方案。此过滤器的方法如下所示:
public override void OnActionExecuting(ActionExecutingContext context)
{
var notMatchedProperties = new Dictionary<string, string>();
// because in ActionArguments there is only one variable - formulationParameters
var mainVariableKey = context.ActionArguments.First().Key;
// the content of FormulationParameters class
var innerParts = context.ActionArguments.First().Value as FormulationParameters;
// conversion from class to dictionary
// the names of the properties are the keys, and their values are values in the dictionary
var classAsDictionary = ClassToDictionaryConverter.Convert(innerParts);
var keys = classAsDictionary.Keys;
foreach (var kvp in context.HttpContext.Request.Query)
{
if (!keys.Contains(kvp.Key, StringComparer.InvariantCultureIgnoreCase))
{
notMatchedProperties.Add(kvp.Key, kvp.Value);
}
}
// fill this dictionary with no matched properties from input
innerParts!.Substitute = notMatchedProperties;
// rewrite the existing value with the new value
context.ActionArguments[mainVariableKey] = innerParts;
base.OnActionExecuting(context);
}
这也不好,因为当我尝试通过 Postman 传递一些参数时它无法正常工作。例如:Codes[0]=1&Codes[1]=2,但是当我这样写 Codes=1&Codes=2 时它工作正常 - 它被映射到 Codes : {1, 2} 并且它被认为是一键Codes。此外,它不是通用的,它看起来像是一种解决方法。
我不知道是否可以使用此操作过滤器,或者我还没有尝试过其他解决方案(但我不知道它)。如果我可以使用这个过滤器,我和我的用户总是需要记住如何正确传递这些参数。因此,我正在寻找一种更通用的方法来在请求来自不同来源(如 Refit、Swagger、Postman)时解析这些参数。
PS 我正在使用 .NET 5,我的应用程序是 Web API 类型
解决方案
推荐阅读
- node.js - 在 Azure 上使用 NodeJs 后端部署 create-react-app
- android - 使用相同的文件名从相机或图库中保存图片会显示新图片,直到打开不同的活动,旧图片再次显示
- python - 如何在 Django FilterSet 中添加默认过滤器?
- go - Golang io.copy 不复制整个数据
- spring - Spring声明性事务按条件给事务管理器名称
- c# - 我是否需要在 ASP.NET Core 3.1 应用程序中添加对 Microsoft.Extensions.Hosting 包的引用?
- azure-devops - SPLA 计划下的 Azure DevOps Basic + 测试计划
- vb.net - VS 2019 Visual Basic导航栏类列表选择时不刷新
- kubernetes - 如何获取我的 K8S 集群的私钥
- java - 如何获取 id 的原始 id 到颜色算法?