简体   繁体   English

ASP.NET Core - ModelBinder - 集合 - 陷入无限/无限循环

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

I am facing an issue with custom ModelBinder ( IModelBinder implementation).我正面临自定义ModelBinderIModelBinder实现)的问题。

This is a model I am trying to bind from query string.这是一个 model 我正在尝试从查询字符串绑定。 The example parameter looks like this:示例参数如下所示:

?Where.Name[eq]=Jakub ?Where.Name[eq]=Jakub

The class I am trying bind to is this:我尝试绑定的 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
    }
}

My attribute annotating this model binder is:我注释此 model 活页夹的属性是:

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

The ModelBinder implementation: 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;
    }
}

The MetadataFilter class resides in following model that should be bound from QueryString. MetadataFilter class 位于 model 之后,应该从 QueryString 绑定。

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

        public MetadataSort Sort { get; set; }

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

Now my code and ModelBinder get's executed correctly and all is getting set correctly.现在我的代码和 ModelBinder 得到正确执行,并且所有设置都正确。 I set ModelBindingResult & returning Task.Completed .我设置ModelBindingResult并返回Task.Completed However it get stuck in an endless loop that I have no idea how to indicate that it should stop.但是它陷入了一个无限循环,我不知道如何指示它应该停止。

The BindModelAsync method gets called infinite amount of times until it hits the limit. BindModelAsync方法被调用无限次,直到达到限制。 The ModelName keeps incrementing as "Where[0]" , "Where[1]" , "Where[2]" , "Where[n]". ModelName不断递增为“Where[0]”“Where[1]”“Where[2]” 、“Where[n]”。

How can I let the Binder know that I am good and that I've bound all the items I needed?我怎样才能让Binder知道我很好,我已经绑定了我需要的所有物品?

Note this is not a duplicate of Inifinite loop during model binding when using [ModelBinder] attribute请注意,这不是Inifinite loop during model binding when using [ModelBinder] 属性的副本

I solved this by putting the ModelBinder attribute on the model property .我通过将ModelBinder属性放在 model 属性上解决了这个问题。 So my Binder instead of trying to bind each item individually which triggers the endless loop, it binds the whole collection at once and that's when this issue disappears.所以我的活页夹不是试图单独绑定每个项目来触发无限循环,而是一次绑定整个集合,这就是这个问题消失的时候。

Final result:最后结果: 在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM