自定义模型绑定程序提供程序始终为 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
的实例,但不会将其反馈 到模型绑定上下文。
另外说明,如果查询字符串段与您尝试绑定的模型的属性名称相匹配,我认为您不需要添加自定义模型绑定器。
我在尝试让自定义模型绑定器用作查询参数时遇到问题,就像我之前在 .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
的实例,但不会将其反馈 到模型绑定上下文。
另外说明,如果查询字符串段与您尝试绑定的模型的属性名称相匹配,我认为您不需要添加自定义模型绑定器。