リクエスト本文を読み取り、行ごとに分割して、コントローラーアクションの文字列配列パラメーターに渡す独自の入力フォーマッターを作成しようとしています。
これは機能します(本体全体を文字列として渡します):
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore(options =>
{
options.InputFormatters.Add(new MyInputFormatter());
}
}
MyInputFormatter.cs
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
{
using (StreamReader reader = new StreamReader(context.HttpContext.Request.Body))
{
return InputFormatterResult.Success(await reader.ReadToEndAsync());
}
}
MyController.cs
[HttpPost("/foo", Name = "Foo")]
public IActionResult Bar([FromBody] string foo)
{
return Ok(foo);
}
これは機能しません (パラメーター foo が null です):
MyInputFormatter.cs
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
{
List<string> input = new List<string>();
using (StreamReader reader = new StreamReader(context.HttpContext.Request.Body))
{
while (!reader.EndOfStream)
{
string line = (await reader.ReadLineAsync()).Trim();
input.Add(line);
}
}
return InputFormatterResult.Success(input.ToArray());
}
MyController.cs
[HttpPost("/foo", Name = "Foo")]
public IActionResult Bar([FromBody] string[] foo)
{
return Ok(string.Join(" ", foo));
}
違いは、コントローラーでは文字列の代わりに文字列の配列を受け入れるようになり、フォーマッターでは入力を 1 行ずつ読み取り、最終的に配列として返すことです。
私は何が欠けていますか?:/
編集:多かれ少なかれ、私のフォーマッタが実際にどのように見えるか(違いがある場合):
public class MyInputFormatter : InputFormatter
{
public MyInputFormatter()
{
this.SupportedMediaTypes.Add(new MediaTypeHeaderValue(MimeType.URI_LIST)); // "text/uri-list"
}
public override bool CanRead(InputFormatterContext context)
{
if (context == null) throw new ArgumentNullException(nameof(context)); // breakpoint here not reached
if (context.HttpContext.Request.ContentType == MimeType.URI_LIST)
return true;
return false;
}
protected override bool CanReadType(Type dataType)
{
return typeof(string[]).IsAssignableFrom(dataType); // breakpoint here not reached
}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
{
List<string> input = new List<string>(); // breakpoint here not reached
using (StreamReader reader = new StreamReader(context.HttpContext.Request.Body))
{
while (!reader.EndOfStream)
{
string line = (await reader.ReadLineAsync()).Trim();
if (string.IsNullOrEmpty(line))
{
continue;
}
if (!line.StartsWith("foo-"))
{
return InputFormatterResult.Failure();
}
input.Add(line.Substring("foo-".Length));
}
}
return InputFormatterResult.Success(input.ToArray());
}