ASP.NET Core 10 Web API如何实现WCF中__type的功能?
在ASP.NET Core Web API中实现基类参数的子类识别(替代WCF的__type机制)
方法一:通过System.Text.Json配置类型信息(推荐)
这是最贴合WCF __type机制的方案,利用ASP.NET Core默认的JSON序列化器实现类型自动识别。
1. 配置Json序列化选项
在Program.cs中添加序列化配置,指定基类Fruit的子类映射,并沿用__type作为类型识别字段:
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver { Modifiers = { typeInfo => { if (typeInfo.Type == typeof(Fruit)) { typeInfo.PolymorphismOptions = new JsonPolymorphismOptions { TypeDiscriminatorPropertyName = "__type", // 和WCF的__type字段对齐 IgnoreUnrecognizedTypeDiscriminators = true, DerivedTypes = { new JsonDerivedType(typeof(Apple), nameof(Apple)), new JsonDerivedType(typeof(Orange), nameof(Orange)) } }; } } } }; });
2. 保持原有Action逻辑不变
你的服务端方法无需修改,序列化器会自动根据__type字段将JSON反序列化为对应子类:
public class FruitController : ControllerBase { [HttpPost("SomeMethod")] public IActionResult SomeMethod([FromBody] Fruit fruit) { if (fruit is Apple apple) { // 处理Apple类型逻辑 return Ok($"处理Apple对象"); } else if (fruit is Orange orange) { // 处理Orange类型逻辑 return Ok($"处理Orange对象"); } else { return Ok("处理未知Fruit子类"); } } }
方法二:客户端配合实现兼容
如果客户端是.NET应用,需要在序列化请求对象时包含__type字段:
var apple = new Apple(); var jsonOptions = new JsonSerializerOptions { TypeInfoResolver = new DefaultJsonTypeInfoResolver { Modifiers = { typeInfo => { if (typeInfo.Type == typeof(Fruit)) { typeInfo.PolymorphismOptions = new JsonPolymorphismOptions { TypeDiscriminatorPropertyName = "__type", DerivedTypes = { new JsonDerivedType(typeof(Apple), nameof(Apple)), new JsonDerivedType(typeof(Orange), nameof(Orange)) } }; } } } } }; var json = JsonSerializer.Serialize(apple, jsonOptions); var content = new StringContent(json, Encoding.UTF8, "application/json"); var httpClient = new HttpClient(); var response = await httpClient.PostAsync("https://你的API地址/SomeMethod", content);
非.NET客户端(如Postman)可手动构造请求JSON:
{ "__type": "Apple", // Apple的其他属性字段 }
方法三:自定义模型绑定器(复杂场景)
如果需要更灵活的类型判断逻辑,可以自定义模型绑定器:
1. 实现自定义绑定器
public class FruitModelBinder : IModelBinder { public Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext == null) throw new ArgumentNullException(nameof(bindingContext)); // 读取请求体JSON using var reader = new StreamReader(bindingContext.HttpContext.Request.Body); var json = reader.ReadToEnd(); // 解析__type字段 var jsonDoc = JsonDocument.Parse(json); if (jsonDoc.RootElement.TryGetProperty("__type", out var typeElement)) { var typeName = typeElement.GetString(); Type targetType = typeName switch { nameof(Apple) => typeof(Apple), nameof(Orange) => typeof(Orange), _ => typeof(Fruit) }; // 反序列化为目标类型 var fruit = JsonSerializer.Deserialize(json, targetType); bindingContext.Result = ModelBindingResult.Success(fruit); } else { // 默认反序列化为基类Fruit var fruit = JsonSerializer.Deserialize<Fruit>(json); bindingContext.Result = ModelBindingResult.Success(fruit); } return Task.CompletedTask; } }
2. 注册绑定器
在Fruit类上标记绑定器:
[ModelBinder(BinderType = typeof(FruitModelBinder))] public class Fruit {}
或者直接在Action参数上指定:
[HttpPost("SomeMethod")] public IActionResult SomeMethod([ModelBinder(BinderType = typeof(FruitModelBinder))] Fruit fruit) { // 原有逻辑不变 }
内容的提问来源于stack exchange,提问作者Khamis Abuelkomboz
相关产品推荐
相关产品推荐

