ASP.NET Core 2:如何让[FromBody]无Content-Type时仍用JSON绑定模型?
解决ASP.NET Core 2中[FromBody]无Content-Type时的JSON绑定问题
这个问题我之前也碰到过,ASP.NET Core默认的JSON格式化器确实只会认Content-Type为application/json(或相关变种)的请求。要让它支持无Content-Type的场景,我们可以通过调整输入格式化器的配置来实现,这里有两种实用方案:
方案一:扩展默认JSON格式化器的支持范围
这是最省心的方法,直接让默认的JsonInputFormatter接受所有媒体类型(包括无Content-Type的请求)。在Startup.cs的ConfigureServices方法里,找到Mvc的配置项修改即可:
using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.Net.Http.Headers; public void ConfigureServices(IServiceCollection services) { services.AddMvc(options => { // 定位到默认的JSON输入格式化器 var jsonInputFormatter = options.InputFormatters .OfType<JsonInputFormatter>() .FirstOrDefault(); if (jsonInputFormatter != null) { // 添加对所有媒体类型的支持,覆盖无Content-Type的情况 jsonInputFormatter.SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("*/*")); } }) .AddJsonOptions(options => { // 按需配置JSON序列化规则,比如驼峰命名: // options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); }); }
配置完成后,不管请求有没有设置Content-Type,只要请求体是合法JSON,[FromBody]就能正常绑定模型。不过要注意:这个方案会让JSON格式化器优先处理所有请求,如果你的API同时需要支持form-data等其他格式,可能需要调整格式化器的优先级。
方案二:自定义输入格式化器(更精准控制)
如果你不想让JSON格式化器“包揽”所有请求,只想针对无Content-Type的情况生效,可以自定义一个格式化器,继承自JsonInputFormatter并做针对性判断:
首先创建自定义格式化器类:
using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using System.Buffers; using Microsoft.Extensions.ObjectPool; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Formatters.Json; public class JsonWithoutContentTypeFormatter : JsonInputFormatter { public JsonWithoutContentTypeFormatter( ILogger<JsonInputFormatter> logger, JsonSerializerSettings serializerSettings, ArrayPool<char> charPool, ObjectPoolProvider objectPoolProvider, MvcOptions mvcOptions, MvcJsonOptions jsonOptions) : base(logger, serializerSettings, charPool, objectPoolProvider, mvcOptions, jsonOptions) { // 保留默认支持的媒体类型,只额外处理无Content-Type的请求 } public override bool CanRead(InputFormatterContext context) { // 仅当请求没有Content-Type或值为空时,启用当前格式化器 var contentType = context.HttpContext.Request.ContentType; if (string.IsNullOrEmpty(contentType)) { return base.CanRead(context); } // 其他情况交给默认格式化器处理 return false; } }
然后在Startup.cs里注册这个自定义格式化器,并把它放到格式化器列表的最前面,确保优先被检查:
public void ConfigureServices(IServiceCollection services) { services.AddMvc(options => { // 获取自定义格式化器所需的依赖项 var serviceProvider = services.BuildServiceProvider(); var logger = serviceProvider.GetRequiredService<ILoggerFactory>() .CreateLogger<JsonInputFormatter>(); var jsonOptions = serviceProvider.GetRequiredService<IOptions<MvcJsonOptions>>().Value; var charPool = ArrayPool<char>.Shared; var objectPoolProvider = serviceProvider.GetRequiredService<ObjectPoolProvider>(); // 实例化自定义格式化器 var customFormatter = new JsonWithoutContentTypeFormatter( logger, jsonOptions.SerializerSettings, charPool, objectPoolProvider, options, jsonOptions); // 插入到格式化器列表首位,保证优先匹配 options.InputFormatters.Insert(0, customFormatter); }) .AddJsonOptions(options => { // 按需配置序列化规则 }); }
这个方案更灵活,只会处理无Content-Type的请求,不会干扰其他格式的正常解析。
两种方案都能解决你的问题,你可以根据自己的API场景选择合适的一种。
内容的提问来源于stack exchange,提问作者alexey
相关产品推荐
相关产品推荐

