You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让ASP.NET Core MVC绑定JSON请求中的简单数据类型?

问题描述

正在将中型.NET 4 ASP.NET MVC应用迁移至.NET 7 ASP.NET Core MVC,大量控制器操作方法使用简单类型做数据绑定,示例代码如下:

public class HomeController : Controller
{
    // ...

    public ActionResult Foo(string bar)
    {
        return Content(bar);
    }

    // ...
}

在旧版ASP.NET MVC中,发送Content-Type: application/json; charset=utf-8的JSON请求:

{ "bar": "BAZ" }

用以下测试代码验证(实际请求来自前端,希望尽量少改前端):

var client = new HttpClient();
var content = new StringContent("{ \"bar\": \"BAZ\" }", new MediaTypeHeaderValue("application/json", "utf-8"));
var response = await client.PostAsync("http://localhost:5261/Home/Foo", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());

旧版中参数能正确绑定并返回BAZ,但ASP.NET Core MVC中bar始终为null。尝试过添加[HttpPost]、[FromBody],仅当创建包含bar属性的复杂类型并加[FromBody]时才生效,也试过给控制器加[ApiController],但不想逐个创建大量「无用」复杂类型,希望找到像旧版那样直接绑定JSON字段到简单类型参数的方法。

解决方案

以下几种方法可实现不创建复杂类型的前提下,完成JSON字段到简单类型参数的绑定:

方法1:使用JObject接收并手动提取值

修改操作方法,用JObject接收整个JSON请求体,手动提取对应字段的值,无需创建额外类型:

[HttpPost]
public ActionResult Foo([FromBody] JObject payload)
{
    string bar = payload["bar"]?.ToString();
    return Content(bar);
}

这种方式改动小,适合快速适配,无需全局配置,直接修改目标方法即可。

方法2:自定义全局模型绑定器

如果有大量这类方法需要适配,可以自定义模型绑定器,让ASP.NET Core自动将JSON中的对应字段绑定到简单类型参数:

  1. 创建自定义模型绑定器:
public class SimpleJsonParameterBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
            throw new ArgumentNullException(nameof(bindingContext));

        // 仅处理POST/PUT的JSON请求
        var request = bindingContext.HttpContext.Request;
        if (!request.ContentType?.StartsWith("application/json", StringComparison.OrdinalIgnoreCase) ?? true)
        {
            bindingContext.Result = ModelBindingResult.Failed();
            return Task.CompletedTask;
        }

        // 读取请求体
        using var reader = new StreamReader(request.Body);
        var json = reader.ReadToEnd();
        if (string.IsNullOrEmpty(json))
        {
            bindingContext.Result = ModelBindingResult.Failed();
            return Task.CompletedTask;
        }

        // 解析JSON并提取与参数名匹配的字段
        var jObj = JObject.Parse(json);
        var parameterName = bindingContext.FieldName;
        var value = jObj[parameterName];

        if (value != null)
        {
            var targetType = bindingContext.ModelType;
            var convertedValue = value.ToObject(targetType);
            bindingContext.Result = ModelBindingResult.Success(convertedValue);
        }
        else
        {
            bindingContext.Result = ModelBindingResult.Failed();
        }

        return Task.CompletedTask;
    }
}
  1. 创建模型绑定提供器:
public class SimpleJsonParameterBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context == null)
            throw new ArgumentNullException(nameof(context));

        // 为简单类型(非复杂类型、非集合)提供绑定器
        if (context.Metadata.IsSimpleType && !context.Metadata.IsCollectionType)
        {
            return new BinderTypeModelBinder(typeof(SimpleJsonParameterBinder));
        }

        return null;
    }
}
  1. 在Program.cs中注册绑定器:
builder.Services.AddControllersWithViews(options =>
{
    // 将自定义绑定器添加到绑定器提供器列表的最前面,确保优先使用
    options.ModelBinderProviders.Insert(0, new SimpleJsonParameterBinderProvider());
});

注册完成后,原来的方法只需添加[HttpPost]即可正常绑定:

[HttpPost]
public ActionResult Foo(string bar)
{
    return Content(bar);
}

方法3:调整ApiController的绑定规则(仅适用于API控制器)

如果控制器标记了[ApiController],可以通过配置修改参数绑定源的优先级,让简单类型优先从请求体获取值:

在Program.cs中添加:

builder.Services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressInferBindingSourcesForParameters = true;
});

然后给简单类型参数添加[FromBody]:

[ApiController]
public class HomeController : ControllerBase
{
    [HttpPost]
    public ActionResult Foo([FromBody] string bar)
    {
        return Content(bar);
    }
}

这种方式需要给每个简单类型参数添加[FromBody],但无需创建复杂类型。

内容的提问来源于stack exchange,提问作者Oskar Sjöberg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 16:40:26