自定义模型绑定程序提供程序始终为 null .net 核心

Custom Model Binder Provider always null .net core

我在尝试让自定义模型绑定器用作查询参数时遇到问题,就像我之前在 .net Framework 4.7 中所做的那样。

为了确保这不是我的对象太复杂的情况,我将模型简化为一个简单的字符串,但即便如此我也无法让它工作。

我有一个简单的模型,我想从查询参数中绑定。

public class SearchModel {
    public string SearchTerms { get; set; }
}

并且我已经配置了 ModelBinder 和 ModelBinderProvider,如图所示 here

public class TestModelBinder : IModelBinder {
    public Task BindModelAsync(ModelBindingContext bindingContext) {
        if (bindingContext.ModelType != typeof(SearchModel)) {
            throw new ArgumentException($"Invalid binding context supplied {bindingContext.ModelType}");
        }

        var model = (SearchModel)bindingContext.Model ?? new SearchModel();

        var properties = model.GetType().GetProperties();
        foreach(var p in properties) {
            var value = this.GetValue(bindingContext, p.Name);
            p.SetValue(model, Convert.ChangeType(value, p.PropertyType), null);
        }

        return Task.CompletedTask;
    }

    protected string GetValue(ModelBindingContext context, string key) {
        var result = context.ValueProvider.GetValue(key);

        return result.FirstValue;
    }
}

public class TestModelBinderProvider : IModelBinderProvider {
    public IModelBinder GetBinder(ModelBinderProviderContext context) {
        if (context == null) {
            throw new ArgumentNullException(nameof(context));
        }

        if (context.Metadata.ModelType == typeof(SearchModel)) {
            var returnType = new BinderTypeModelBinder(typeof(TestModelBinder));
            return returnType;
        }

        return null;
    }
}

如 Microsoft 文档的最后一步所述,我更新了 Startup.cs 中的 ConfigureServices 方法以包含 BinderProvider。

services.AddMvc(options => {
            options.ModelBinderProviders.Insert(0, new TestModelBinderProvider());
        })
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

但是当我用 url 调用我的搜索端点时,例如“https://localhost:44387/api/testbinding?searchTerms=newSearch”,我总是看到 "request == null True" 的 return,即使我正确地看到它如果我逐步调试,请点击自定义绑定并正确绑定,任何人都可以指出我做错了什么的正确方向吗?

[Route("api/[controller]")]
[ApiController]
public class TestBindingController : ControllerBase {

    [HttpGet()]
    public IActionResult GetResult([FromQuery] SearchModel request) {
        return Ok($"request == null {request == null}");
    }

}

我认为如果设置模型绑定操作结果的语句你错过了什么,正如你在文档 this section 中的 AuthorEntityBinder 代码示例中看到的那样:

bindingContext.Result = ModelBindingResult.Success(model);

您的模型绑定器实现确实创建了 SearchModel 的实例,但不会将其反馈 到模型绑定上下文。


另外说明,如果查询字符串段与您尝试绑定的模型的属性名称相匹配,我认为您不需要添加自定义模型绑定器。