ASP.NET Core如何按TransactionType条件使用多模型实现单端点处理交易
实现方案
步骤1:重构模型结构,抽离公共基类
将三个模型共有的属性提取到抽象基类,三个交易模型分别继承基类,按需扩展自有属性:
// 公共交易请求基类 public abstract class TransactionBaseRequest { public string TransactionType { get; set; } public CardDetails CardDetails { get; set; } } // 支付请求模型 public class PaymentRequest : TransactionBaseRequest { // 补充支付场景独有属性,例如订单号、支付金额等 public string OrderNo { get; set; } public decimal PayAmount { get; set; } } // 退款请求模型 public class RefundRequest : TransactionBaseRequest { // 补充退款场景独有属性,例如原交易号、退款金额等 public string OriginalTransactionId { get; set; } public decimal RefundAmount { get; set; } } // 重复交易请求模型 public class RepeatRequest : TransactionBaseRequest { // 补充重复交易场景独有属性,例如原授权码等 public string OriginalAuthCode { get; set; } }
步骤2:实现自定义JSON反序列化转换器
ASP.NET Core 6默认使用System.Text.Json做序列化,自定义转换器可以根据TransactionType字段自动反序列化为对应子类对象:
using System.Text.Json; using System.Text.Json.Serialization; public class TransactionRequestConverter : JsonConverter<TransactionBaseRequest> { public override TransactionBaseRequest Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 先加载JSON节点 var jsonNode = JsonNode.Parse(ref reader); // 读取交易类型字段 var transactionType = jsonNode["TransactionType"]?.GetValue<string>()?.ToLower(); if (string.IsNullOrWhiteSpace(transactionType)) { throw new ArgumentException("请求缺少TransactionType参数"); } // 根据交易类型反序列化为对应模型 return transactionType switch { "payment" => jsonNode.Deserialize<PaymentRequest>(options), "refund" => jsonNode.Deserialize<RefundRequest>(options), "repeat" => jsonNode.Deserialize<RepeatRequest>(options), _ => throw new NotSupportedException($"不支持的交易类型:{transactionType}") }; } public override void Write(Utf8JsonWriter writer, TransactionBaseRequest value, JsonSerializerOptions options) { // 序列化时按实际类型输出 JsonSerializer.Serialize(writer, value, value.GetType(), options); } }
步骤3:注册自定义转换器
在Program.cs中把自定义转换器注册到系统JSON配置中:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers() .AddJsonOptions(options => { // 注册自定义交易请求转换器 options.JsonSerializerOptions.Converters.Add(new TransactionRequestConverter()); }); // 其他服务注册、中间件配置逻辑保持不变 var app = builder.Build(); app.MapControllers(); app.Run();
步骤4:调整控制器逻辑
控制器接口直接用基类作为入参,根据实际类型分发到对应业务逻辑即可:
[HttpPost] [Route("all-payment")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task<IActionResult> HandleTransaction([FromBody] TransactionBaseRequest request) { object result = request switch { PaymentRequest paymentReq => await _paymentService.ProcessPayment(paymentReq), RefundRequest refundReq => await _refundService.ProcessRefund(refundReq), RepeatRequest repeatReq => await _repeatService.ProcessRepeat(repeatReq), _ => throw new NotSupportedException("不支持的交易类型") }; return Ok(result); }
如果你项目用的是Newtonsoft.Json而非System.Text.Json,实现思路完全一致,只需继承Newtonsoft的JsonConverter实现对应逻辑即可。
内容的提问来源于stack exchange,提问作者hanushic
相关产品推荐
相关产品推荐

