在Swagger UI与C# ASP.NET Core中,POST请求体能否传递逐字字符串字面量?
解决ASP.NET Core MVC中[FromBody]字符串原样传递的问题
先说说问题出在哪:
当用[FromBody] string接收参数时,ASP.NET Core默认会按JSON格式解析请求体。但JSON有自己的规范:字符串必须用双引号包裹,所以就出现了你遇到的情况:
- 输入
"quoted text",JSON解析器会自动剥掉外层引号,只返回quoted text - 输入
text,这不是合法的JSON值(JSON不允许裸字符串,只能是null、布尔值、数字或者带引号的字符串),直接触发400验证错误
要实现类似C#逐字字符串那种「输啥返回啥」的效果,给你两种可行方案:
方案1:改用text/plain格式接收纯文本
这是最直接的方式,让接口接收纯文本而非JSON,请求体内容会原封不动传递到方法里。
第一步:写个text/plain的输入格式化器
创建自定义的输入格式化器,处理text/plain类型的请求:
public class TextPlainInputFormatter : InputFormatter { public TextPlainInputFormatter() { SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/plain")); } protected override bool CanReadType(Type type) { return type == typeof(string); } public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context) { using var reader = new StreamReader(context.HttpContext.Request.Body); var content = await reader.ReadToEndAsync(); return await InputFormatterResult.SuccessAsync(content); } }
第二步:注册格式化器到MVC
在Program.cs里把这个格式化器加到MVC的输入格式列表里:
builder.Services.AddControllers(options => { // 插入到最前面,优先使用这个格式化器处理text/plain请求 options.InputFormatters.Insert(0, new TextPlainInputFormatter()); });
第三步:优化Swagger体验(可选)
给接口加上[Consumes("text/plain")],让Swagger自动设置正确的Content-Type:
[MapToApiVersion("1.0")] [HttpPost("TestPostBody")] [Consumes("text/plain")] public IActionResult TestPostBody([FromBody] string bodyOfStrings) { return Ok(bodyOfStrings); }
现在测试就正常了:
- 输入
"quoted text",接口原样返回"quoted text" - 输入
text也能直接返回text,不会报400错误
方案2:直接读取原始请求体
如果不想改全局配置,也可以在action里直接读请求体的原始内容:
[MapToApiVersion("1.0")] [HttpPost("TestPostBody")] public async Task<IActionResult> TestPostBody() { using var reader = new StreamReader(Request.Body); var bodyContent = await reader.ReadToEndAsync(); return Ok(bodyContent); }
这种方式不用加[FromBody]特性,不管请求体是什么格式,都会原封不动读出来返回。
测试注意事项
用方案1的话,Swagger会自动显示text/plain的输入框;用方案2的话,需要在Swagger里手动把Content-Type改成text/plain(或者任意类型),输入内容就能正常测试了。
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

