どういうこと?
こんなコントローラを書いたとする。例なのでバリデーションのチェックや例外とかは気にしない。
[HttpPost("/api/post_something")]
public async Task<ActionResult<bool>> PostSomething([FromBody] SomeRequest request)
{
var ret = await SomeService.DoSomething(request);
return Ok(ret);
}
ここでSomeRequest
は自分で定義したクラスだ。例えばこんな感じだとしよう。
public class SomeRequest
{
public string Memo { get; set; }
public User UserInfo { get; set; }
}
Userクラスは名前と年齢を持つだけのクラスとする。折角なのでコンストラクタも定義しておくとしよう。
public class User
{
public string Name { get; set; }
public uint Age { get; set; }
public User(string name, uint age)
{
Name = name;
Age = age;
}
}
至ってシンプル。それっぽいjsonを書いてリクエストを投げてみよう。
{
"memo": "これは試験的に投げるリクエストだよ。",
"user_info":
{
"name": "ほげ子",
"age": 17
}
}
するとrequestはSomeRequestのインスタンスに正しくマッピングされず、nullになる・・・。
一体何故?
解答
Userクラスにデフォルトコンストラクタを定義していないのが原因。こうすれば正しくマップされる。
public class User
{
public string Name { get; set; }
public uint Age { get; set; }
public User() {}
public User(string name, uint age)
{
Name = name;
Age = age;
}
}
経緯
複数のクラスを入れ子にしたクラスのメンバーを持ったリクエストメッセージを指定したら、どうにもリクエストが正しくマップされなくて小一時間悩んだのがきっかけ。例はかなり単純なのですぐに気づきますが、何のエラーも出ないので遭遇した時は頭を抱えました。