检测自定义模型绑定中的可用键
Detecting available keys in a custom model binding
目前正在使用 ASP.NET Core 2.2.0
我有一个控制器操作 (POST),它需要支持具有多个任意命名的输入参数的客户端请求(我事先不知道有多少个键或它们的名称)。我的想法是,这些参数应该绑定到控制器操作中的集合参数,例如 Dictionary<string,object>
,但如果有其他方法,我对此很灵活。
我正在尝试使用自定义模型绑定来执行此操作。绑定上下文中值提供者的可用 public 接口似乎要求我知道键名才能获取值,例如
valueProviderResult = bindingContext.ValueProvider.GetValue("keyName");
当然这无助于满足规定的要求。
调试时我发现密钥就在那里,隐藏在值提供程序的 private 部分中,但我还没有找到利用它的优质方法。
bindingContext.ValueProvider[1]._values.Keys
//_values is private
- 是否有一些我错过的现有活页夹可以做到这一点?
- 是否有一些 public 访问密钥的方法?
- 键被设计完全隐藏是出于某种原因吗?
我确实找到了一个合适的解决方案。对于其他有兴趣发现输入参数名称的人,对我来说关键是要注意(在调试时)虽然 bindingContext.ValueProvider
被声明为 IValueProvider
,但它在 运行 时的实现类型(至少在我的示例)是 CompositeValueProvider
,它确实添加了一个有用的方法。 (这方面的 MS 文档相对没有帮助,我的搜索没有找到一个有启发性的例子)
对于某些支持背景,CompositeValueProvider
支持名称中带有前缀的输入参数的概念,尽管您不需要使用前缀来实现我规定的目标。支持两种语法版本,prefix.name
和 prefix[name]
。
所以我做了类似下面的事情:
using Microsoft.AspNetCore.Mvc.ModelBinding;
using System.Collections.Generic;
using System.Threading.Tasks;
// in my custom binder class derived from IModelBinder
public async Task BindModelAsync(ModelBindingContext bindingContext)
{
var compositeValueProvider = bindingContext.ValueProvider as CompositeValueProvider;
// For unprefixed names:
// This also returns prefixes of prefixed names so you can recursively find the names
var callerProvidedKeys = compositeValueProvider.GetKeysFromPrefix("");
// or for a known prefix name
//var callerProvidedKeys = compositeValueProvider.GetKeysFromPrefix(somePrefix);
foreach (KeyValuePair<string, string> kvp in callerProvidedKeys) {
// You can but don't have to access values through `CompositeValueProvider`
var valueProviderResult = bindingContext.ValueProvider.GetValue(kvp.Value);
...
}
...
}
GetKeysFromPrefix
returns IDictionary<string,string>
其中键只是名称部分,值是包括前缀的完整参数名称。然后可以使用全名来提取参数值。
目前正在使用 ASP.NET Core 2.2.0
我有一个控制器操作 (POST),它需要支持具有多个任意命名的输入参数的客户端请求(我事先不知道有多少个键或它们的名称)。我的想法是,这些参数应该绑定到控制器操作中的集合参数,例如 Dictionary<string,object>
,但如果有其他方法,我对此很灵活。
我正在尝试使用自定义模型绑定来执行此操作。绑定上下文中值提供者的可用 public 接口似乎要求我知道键名才能获取值,例如
valueProviderResult = bindingContext.ValueProvider.GetValue("keyName");
当然这无助于满足规定的要求。
调试时我发现密钥就在那里,隐藏在值提供程序的 private 部分中,但我还没有找到利用它的优质方法。
bindingContext.ValueProvider[1]._values.Keys
//_values is private
- 是否有一些我错过的现有活页夹可以做到这一点?
- 是否有一些 public 访问密钥的方法?
- 键被设计完全隐藏是出于某种原因吗?
我确实找到了一个合适的解决方案。对于其他有兴趣发现输入参数名称的人,对我来说关键是要注意(在调试时)虽然 bindingContext.ValueProvider
被声明为 IValueProvider
,但它在 运行 时的实现类型(至少在我的示例)是 CompositeValueProvider
,它确实添加了一个有用的方法。 (这方面的 MS 文档相对没有帮助,我的搜索没有找到一个有启发性的例子)
对于某些支持背景,CompositeValueProvider
支持名称中带有前缀的输入参数的概念,尽管您不需要使用前缀来实现我规定的目标。支持两种语法版本,prefix.name
和 prefix[name]
。
所以我做了类似下面的事情:
using Microsoft.AspNetCore.Mvc.ModelBinding;
using System.Collections.Generic;
using System.Threading.Tasks;
// in my custom binder class derived from IModelBinder
public async Task BindModelAsync(ModelBindingContext bindingContext)
{
var compositeValueProvider = bindingContext.ValueProvider as CompositeValueProvider;
// For unprefixed names:
// This also returns prefixes of prefixed names so you can recursively find the names
var callerProvidedKeys = compositeValueProvider.GetKeysFromPrefix("");
// or for a known prefix name
//var callerProvidedKeys = compositeValueProvider.GetKeysFromPrefix(somePrefix);
foreach (KeyValuePair<string, string> kvp in callerProvidedKeys) {
// You can but don't have to access values through `CompositeValueProvider`
var valueProviderResult = bindingContext.ValueProvider.GetValue(kvp.Value);
...
}
...
}
GetKeysFromPrefix
returns IDictionary<string,string>
其中键只是名称部分,值是包括前缀的完整参数名称。然后可以使用全名来提取参数值。