ASP.NET Core Pitfalls – Posting a String
This is another post on my ASP.NET Core pitfalls series. It is actually related to this one ASP.NET Core Pitfalls – Null Models in Post Requests.
What happens if you try to submit a string containing JSON as a POST? I mean, you always submit strings, but this time you don't want for it to be parsed into some class. Like this:[HttpPost]
public IActionResult PostString([FromBody] string json) { ... }
You may be surprised to find out that this fails with a HTTP 415 Unsupported Media Type.
Now, you might be tempted to add an [Consumes] attribute to it, such as:
[HttpPost]
[Consumes("application/json")]
public IActionResult PostString([FromBody] string json) { ... }
And this will actually work! The problem is, or could be, that it requires the sender to send the appropriate Content-Type header ("application/json").
Another, better, solution is to just read the string from the from the request stream:
[HttpPost]
public IActionResult PostString()
{
using var reader = new StreamReader(HttpContext.Request.Body));
var json = reader.ReadToEnd();
...
}
Of course, this could be made asynchronous, as StreamReader has a ReadToEndAsync method.
Yet another option is to add a custom input formatter, a class that implements IInputFormatter, one that just accepts a string, which needs to be registered globally:
builder.Services.AddControllersWithViews(static options =>
{
options.InputFormatters.Insert(0, new StringInputFormatter());
});
One example would be:
internal class StringInputFormatter : IInputFormatter
{
public bool CanRead(InputFormatterContext context)
{
var canRead = context.HttpContext.Request.Method == HttpMethods.Post
&& context.HttpContext.Request.ContentLength > 0;
return canRead;
}
public async Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
{
using var reader = new StreamReader(context.HttpContext.Request.Body);
var content = await reader.ReadToEndAsync();
return await InputFormatterResult.SuccessAsync(content);
}
}
As you can see that there's a lot more involved than with the other two solutions.
Hope this comes useful!
Comments
Post a Comment