ASP.NET Core继承ControllerBase时如何绑定JSON体多个原始值(低改动)
在ASP.NET Core中实现JSON请求体绑定多个原始类型参数(最小改动)
针对你要迁移的场景,以下几种方案可以用最小的代码改动实现需求,按推荐程度排序:
方案1:使用DTO类(官方推荐,改动极小)
这是ASP.NET Core处理请求体绑定的标准方式,代码改动最少且符合框架设计:
- 定义一个与JSON结构匹配的简单DTO类:
public class FooRequest { public string Text { get; set; } public int Value { get; set; } }
- 修改Action参数,替换为这个DTO并添加
[FromBody]特性,同时将返回类型改为ASP.NET Core兼容的IActionResult:
public class FooController : Microsoft.AspNetCore.Mvc.ControllerBase { public async Task<IActionResult> GetAsync([FromBody] FooRequest request) { // 直接使用 request.Text 和 request.Value,原有逻辑无需修改 // ... } }
方案2:用JObject直接解析(无需新增类)
如果不想额外创建DTO类,可以借助Newtonsoft.Json的JObject直接解析请求体:
using Newtonsoft.Json.Linq; public class FooController : Microsoft.AspNetCore.Mvc.ControllerBase { public async Task<IActionResult> GetAsync([FromBody] JObject requestBody) { string text = requestBody["text"]?.ToString(); int value = requestBody["value"]?.Value<int>() ?? 0; // 原有逻辑直接复用text和value变量 // ... } }
注:确保项目已安装Newtonsoft.Json NuGet包,ASP.NET Core 3.0+默认使用System.Text.Json,若要切换回Newtonsoft.Json需额外配置。
方案3:自定义模型绑定器(完全保留原Action参数)
如果希望完全保留原Action的参数列表(不修改参数定义),可以通过自定义模型绑定器实现:
- 编写绑定器和绑定器提供器:
using Microsoft.AspNetCore.Mvc.ModelBinding; using Newtonsoft.Json; using System.IO; using System.Threading.Tasks; public class JsonBodyPrimitiveBinder : IModelBinder { public async Task BindModelAsync(ModelBindingContext bindingContext) { // 读取请求体JSON using var reader = new StreamReader(bindingContext.HttpContext.Request.Body); var jsonContent = await reader.ReadToEndAsync(); var jsonData = JsonConvert.DeserializeObject<dynamic>(jsonContent); // 匹配参数名并赋值 var paramName = bindingContext.FieldName; var paramValue = jsonData[paramName]; if (paramValue != null) { var typedValue = Convert.ChangeType(paramValue, bindingContext.ModelType); bindingContext.Result = ModelBindingResult.Success(typedValue); } } } public class JsonBodyPrimitiveBinderProvider : IModelBinderProvider { public IModelBinder GetBinder(ModelBinderProviderContext context) { if (context == null) throw new ArgumentNullException(nameof(context)); // 仅对原始类型和字符串应用此绑定器 if (context.Metadata.IsPrimitive || context.Metadata.ModelType == typeof(string)) { return new JsonBodyPrimitiveBinder(); } return null; } }
- 在Program.cs(或Startup.cs)中注册绑定器:
// ASP.NET Core 6+ Program.cs builder.Services.AddControllers(options => { // 将自定义绑定器放在最前面,优先使用 options.ModelBinderProviders.Insert(0, new JsonBodyPrimitiveBinderProvider()); });
- 原Action只需修改返回类型,参数完全保留:
public class FooController : Microsoft.AspNetCore.Mvc.ControllerBase { public async Task<IActionResult> GetAsync(string text, int value) { // 原有逻辑完全不变,直接使用text和value // ... } }
注:此方案需注意HTTP方法规范——GET请求默认不读取请求体,建议将接口改为POST/PUT,若坚持用GET需额外配置允许读取请求体(不推荐)。
内容的提问来源于stack exchange,提问作者Linus
相关产品推荐
相关产品推荐

