I had to write a custom IInputFormatter
to ensure my body content was always interpreted as a string.
I also was in the situation where updating all of the API clients was infeasible.
The following will ensure that any [FromBody]
parameters will be interpreted as strings, even if they are not quote-wrapped by the caller.
public class JsonStringInputFormatter : TextInputFormatter
{
public JsonStringInputFormatter() : base()
{
SupportedEncodings.Add(UTF8EncodingWithoutBOM);
SupportedEncodings.Add(UTF16EncodingLittleEndian);
SupportedMediaTypes.Add(MediaTypeNames.Application.Json);
}
public override bool CanRead(InputFormatterContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
return context.ModelType == typeof(string);
}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(
InputFormatterContext context, Encoding encoding)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
using (var streamReader = new StreamReader(
context.HttpContext.Request.Body,
encoding))
{
return await InputFormatterResult.SuccessAsync(
(await streamReader.ReadToEndAsync()).Trim('"'));
}
}
}
Trimming quotes from the body allows this to be forwards-compatible for body content that is correctly formatted and quote-wrapped.
Ensure that it is registered in your startup before the System.Text.Json
formatter:
services.AddControllers()
.AddMvcOptions(options =>
{
options.InputFormatters.Insert(
0,
new JsonStringInputFormatter());
});