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中的自定义模型绑定?
 
				
         
 
            
        基础教程推荐
- 如何动态获取文本框中datagridview列的总和 2022-01-01
- 是否可以在 asp classic 和 asp.net 之间共享会话状态 2022-01-01
- 全局 ASAX - 获取服务器名称 2022-01-01
- 从 VS 2017 .NET Core 项目的发布目录中排除文件 2022-01-01
- 首先创建代码,多对多,关联表中的附加字段 2022-01-01
- 错误“此流不支持搜索操作"在 C# 中 2022-01-01
- 经典 Asp 中的 ResolveUrl/Url.Content 等效项 2022-01-01
- 在 VS2010 中的 Post Build 事件中将 bin 文件复制到物 2022-01-01
- JSON.NET 中基于属性的类型解析 2022-01-01
- 将事件 TextChanged 分配给表单中的所有文本框 2022-01-01
 
    	 
    	 
    	 
    	 
    	 
    	 
    	 
    	 
						 
						 
						 
						 
						 
				 
				 
				 
				