Custom model binding in AspNet Core WebApi?(AspNet Core WebApi中的自定义模型绑定?)
问题描述
有人有使用多态模型绑定的自定义模型绑定的工作示例吗?我正在尝试this example(这是针对MVC而不是Api项目的),但它不适用于API项目。我认为在填充ValueProvider
方面缺少一些步骤,但我找不到任何与此相关的资源(AspNet Core 3.1)。
我到目前为止的尝试:
DTO:
public abstract class Device
{
public string Kind { get; set; }
}
public class Laptop : Device
{
public string CPUIndex { get; set; }
}
public class SmartPhone : Device
{
public string ScreenSize { get; set; }
}
自定义模型绑定器实现:
public class DeviceModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context.Metadata.ModelType != typeof(Device))
{
return null;
}
var subclasses = new[] { typeof(Laptop), typeof(SmartPhone), };
var binders = new Dictionary<Type, (ModelMetadata, IModelBinder)>();
foreach (var type in subclasses)
{
var modelMetadata = context.MetadataProvider.GetMetadataForType(type);
binders[type] = (modelMetadata, context.CreateBinder(modelMetadata));
}
return new DeviceModelBinder(binders);
}
}
public class DeviceModelBinder : IModelBinder
{
private Dictionary<Type, (ModelMetadata, IModelBinder)> binders;
public DeviceModelBinder(Dictionary<Type, (ModelMetadata, IModelBinder)> binders)
{
this.binders = binders;
}
public async Task BindModelAsync(ModelBindingContext bindingContext)
{
var modelKindName = ModelNames.CreatePropertyModelName(bindingContext.ModelName, nameof(Device.Kind));
var modelTypeValue = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
IModelBinder modelBinder;
ModelMetadata modelMetadata;
if (modelTypeValue.FirstValue == "Laptop")
{
(modelMetadata, modelBinder) = binders[typeof(Laptop)];
}
else if (modelTypeValue.FirstValue == "SmartPhone")
{
(modelMetadata, modelBinder) = binders[typeof(SmartPhone)];
}
else
{
bindingContext.Result = ModelBindingResult.Failed();
return;
}
var newBindingContext = DefaultModelBindingContext.CreateBindingContext(
bindingContext.ActionContext,
bindingContext.ValueProvider,
modelMetadata,
bindingInfo: null,
bindingContext.ModelName);
await modelBinder.BindModelAsync(newBindingContext);
bindingContext.Result = newBindingContext.Result;
if (newBindingContext.Result.IsModelSet)
{
// Setting the ValidationState ensures properties on derived types are correctly
bindingContext.ValidationState[newBindingContext.Result] = new ValidationStateEntry
{
Metadata = modelMetadata,
};
}
}
}
我按如下方式注册模型绑定器提供程序:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(o => o.ModelBinderProviders.Insert(0, new DeviceModelBinderProvider()));
}
然后我的控制器:
[ApiController]
[Route("test")]
public class TestController : ControllerBase
{
[HttpPost]
public IActionResult Test(Device dto)
{
var x = dto;
return Ok();
}
}
我发布了一个json请求正文,如下所示:
{
"ScreenSize": "1",
"Kind": "SmartPhone"
}
真的很喜欢这方面的文档,因为有太多的魔力正在发生。我的备用方法是手动从请求中解析HttpContent并反序列化。但我希望使用模型活页夹方法,如示例中所示。我看到的唯一两件奇怪的事情是,bindingContext.ModelName
是空的,bindingContext.ValueProvider
只有一个包含action
和controller
键的路由值提供者。因此,它看起来甚至没有将主体解析为值提供程序。
JSON
当推荐答案数据不与模型bindingValue提供器子系统的其余部分交互时,将使用它。对于此场景,您必须为您正在使用的JSON库编写一个转换器。
详细信息:
- Microsoft docs: How to write custom converters for JSON serialization (marshalling) in .NET
- Newtonsoft docs: Custom JsonConverter
相关信息
- pranavkm's answer on GitHub(此答案归功于pranavkm)
- Polymorphic model binding in AspNetCore 3.1 Api
这篇关于AspNet Core WebApi中的自定义模型绑定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:AspNet Core WebApi中的自定义模型绑定?
基础教程推荐
- 创建属性设置器委托 2022-01-01
- C# - 如何列出发布到 ASPX 页面的变量名称和值 2022-01-01
- 我什么时候应该使用 GC.SuppressFinalize()? 2022-01-01
- 使用 SED 在 XML 标签之间提取值 2022-01-01
- 如何使用OpenXML SDK将Excel转换为CSV? 2022-01-01
- 覆盖 Json.Net 中的默认原始类型处理 2022-01-01
- 从 VB6 迁移到 .NET/.NET Core 的最佳策略或工具 2022-01-01
- Page.OnAppearing 中的 Xamarin.Forms Page.DisplayAlert 2022-01-01
- C# - 将浮点数转换为整数...并根据余数更改整数 2022-01-01
- 当键值未知时反序列化 JSON 2022-01-01