aspnet core request body 支持 plain text

Intro

我们有个接口需要给非研发人员使用,这个 API 大概功能是业务人员用来做简繁转换,原来有一个接口但是需要把要翻译的内容转成 json,返回的 response 也是 json,对于业务人员来说,用起来属实有些麻烦,所以我们要新加一个 API 用户可以直接输入要转换的文本,并将转换后的文本直接输出,用户输入的内容是纯文本

InputFormatter.

在 asp.net core mvc 中我们可以只用 input formatter 来进行扩展尚未支持的 media-type,之前我们有分享过一个自定义 content-type base-64 json 感兴趣的小伙伴也可以看一下

这次我们需要支持 text/plain,默认的 input formatter 只有 json,并且框架里没有类似的东西,我们只能自己实现一个 formatter 了,在 GitHub 上找到一个类似的实现,没有在框架里,在测试代码里,可以参考:https://github.com/dotnet/aspnetcore/blob/2d3a0783fee9fc0b3a02a0813b363eb321fe8be2/src/Mvc/test/WebSites/FormatterWebSite/StringInputFormatter.cs#L10

读取 request body 的地方我们优化一下,就得到了下面的版本:

public sealed class PlainTextInputFormatter : TextInputFormatter
{
    public PlainTextInputFormatter()
    {
        SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/plain"));

        SupportedEncodings.Add(Encoding.UTF8);
        SupportedEncodings.Add(Encoding.Unicode);
    }

    public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
    {
        using var reader = context.ReaderFactory(context.HttpContext.Request.Body, encoding);
        var rawContent = await reader.ReadToEndAsync();
        return await InputFormatterResult.SuccessAsync(rawContent);
    }
}

Sample

我们注册了这个 PlainTextInputFormatter 之后就可以支持 plain text 的输入了,参考下面的示例

在 Program 或者 Startup 中注册我们的 PlainTextInputFormatter

builder.Services.AddControllers(options =>
{
    options.InputFormatters.Add(new PlainTextInputFormatter());
});

这样我们的应用就支持了 plain text 的 request body 了,再来看下我们的 API 示例:

[HttpPost("RawTextFormatterTest")]
[Consumes("text/plain")]
public Result RawTextFormatterTest([FromBody] string input)
{
    return Result.Success<string>(input);
}

通过指定 [Consumes("text/plain")] 来指定 API 支持的 media type 为 text/plain

我们来看下 swagger 会是什么样子:

aspnet core request body 支持 plain text

aspnet core request body 支持 plain text

可以看到我们的 input 被正确的返回回来了,我们的 plain text 支持就可以了

More

Github 上提了 issue,希望框架能够默认支持 plain text,这样我们就不需要自己扩展了 https://github.com/dotnet/aspnetcore/issues/49168

如果大家也有这样的需求,也请大家帮忙支持一下这个 Github issue 哈,目前官方觉得用的场景较少,暂时不太考虑,如果大家需求多的话可能就会考虑加在框架里。