ASP.NET Core - ModelBinder - 集合 - 卡在无限/无限循环中

ASP.NET Core - ModelBinder - Collection - stuck in endless / infinite loop

我遇到了自定义 ModelBinderIModelBinder 实现)的问题。

这是我尝试从查询字符串绑定的模型。示例参数如下所示:

?Where.Name[eq]=Jakub

我尝试绑定的 class 是这样的:

[MetadataFilterBinder]
public class MetadataFilter
{
    public string Term { get; set; }

    public string Field { get; set; }

    public FilterClause Clause { get; set; }

    // Where.Name[eq]=Jakub
    public static bool TryParse(string s, out MetadataFilter metadataFilter)
    {
        // commented out for brevity
    }
}

我注释此模型活页夹的属性是:

public class MetadataFilterBinderAttribute : ModelBinderAttribute
    {
        public MetadataFilterBinderAttribute() : base(typeof(MetadataFilterBinder))
        {
            BindingSource = BindingSource.Query;
        }
    }

ModelBinder 实现:

public class MetadataFilterBinder : IModelBinder
    {
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
                throw new ArgumentNullException(nameof(bindingContext));

            var modelName = bindingContext.ModelName;

            var queryStringKeyName = new string(modelName.Where(char.IsLetter).ToArray());

            var whereKeyValue = bindingContext.HttpContext.Request.Query
                .FirstOrDefault(q => q.Key.StartsWith($"{queryStringKeyName}.", StringComparison.InvariantCultureIgnoreCase));

            if (whereKeyValue.Key == string.Empty)
                return Task.CompletedTask;

            var valueProviderResult = bindingContext.ValueProvider.GetValue(whereKeyValue.Key);
            if (valueProviderResult == ValueProviderResult.None)
                return Task.CompletedTask;

            bindingContext.ModelState.SetModelValue(modelName, valueProviderResult);

            if (string.IsNullOrEmpty(valueProviderResult.FirstValue))
                return Task.CompletedTask;
            var result = MetadataFilter.TryParse($"{whereKeyValue.Key}={whereKeyValue.Value}", out var metadataFilter);
            if (result)
            {
                bindingContext.Result = ModelBindingResult.Success(metadataFilter);
            }
            else
            {
                bindingContext.ModelState.TryAddModelError(modelName, "Invalid metadata filter value.");
            }
            
            return Task.CompletedTask;
    }
}

MetadataFilter class 驻留在应从 QueryString 绑定的以下模型中。

public class Metadata : IMetadataPaginable, IMetadataSortable, IMetadataFilterable
    {
        public MetadataPaging Paging { get; set; }

        public MetadataSort Sort { get; set; }

        public IReadOnlyCollection<MetadataFilter> Where { get; set; }
    }

现在我的代码和 ModelBinder 得到正确执行,所有设置都正确。我设置 ModelBindingResult 并返回 Task.Completed。但是它陷入了无限循环,我不知道如何指示它应该停止。

BindModelAsync 方法被调用无限次,直到达到限制。 ModelName 保持递增 "Where[0]", "Where[1]", "哪里[2]", "哪里[n]".

如何让Binder知道我很好,我已经绑定了我需要的所有项目?

请注意,这不是

的副本

我通过将 ModelBinder 属性 放在模型 属性 上解决了这个问题。所以我的 Binder 不是试图单独绑定每个项目来触发无限循环,而是一次绑定整个集合,那时这个问题就消失了。

最终结果: