检测自定义模型绑定中的可用键

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
  1. 是否有一些我错过的现有活页夹可以做到这一点?
  2. 是否有一些 public 访问密钥的方法?
  3. 键被设计完全隐藏是出于某种原因吗?

我确实找到了一个合适的解决方案。对于其他有兴趣发现输入参数名称的人,对我来说关键是要注意(在调试时)虽然 bindingContext.ValueProvider 被声明为 IValueProvider,但它在 运行 时的实现类型(至少在我的示例)是 CompositeValueProvider,它确实添加了一个有用的方法。 (这方面的 MS 文档相对没有帮助,我的搜索没有找到一个有启发性的例子)

对于某些支持背景,CompositeValueProvider 支持名称中带有前缀的输入参数的概念,尽管您不需要使用前缀来实现我规定的目标。支持两种语法版本,prefix.nameprefix[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> 其中键只是名称部分,值是包括前缀的完整参数名称。然后可以使用全名来提取参数值。