ASP.NET Core 2.0を使用しており、次のように注釈が付けられた要求オブジェクトがあります。
public class MyRequest
{
[Required]
public Guid Id { get; set; }
[Required]
public DateTime EndDateTimeUtc { get; set; }
[Required]
public DateTime StartDateTimeUtc { get; set; }
}
そして私のコントローラーでは:
public async Task<IActionResult> HandleRequest([FromBody] MyRequest request)
{ /* ... */ }
モデルバインディングの問題に気づきました。ヘッダーContent-Type
がapplication/json
に設定され、本文が空のリクエストを送信すると、予想どおり、コントローラーのrequest
はnull
で、ModelState.IsValid
はfalse
です。
しかし、私がこのような体を持っているとき:
{
"hello": "a-string-value!"
}
私のrequest
はnull
ではなく、すべてにデフォルト値があり、ModelState.IsValid
はtrue
です。
もちろん、これはすべてのRequired
プロパティが欠落していて、既存の名前だけがそこのプロパティと一致しないときに発生します(この単一パラメーターのタイプでさえ、string
であり、モデルのどのタイプとも一致しません) 。
したがって、ある意味で、これらのRequired
属性は、リクエストに何も含まれていない場合は機能しているように見えますが、リクエストが空でない場合は何もしません。
この質問を準備しているときに、JsonRequired
属性もあり、存在するプロパティを処理しているように見えることに気付きました。
では、Required
とJsonRequired
の違いは何ですか?
Required
属性を正しく機能させるには、プロパティをnull許容にする必要があります。
public class MyRequest
{
[Required]
public Guid? Id { get; set; }
[Required]
public DateTime? EndDateTimeUtc { get; set; }
[Required]
public DateTime? StartDateTimeUtc { get; set; }
}
Id
、EndDateTimeUtc
、またはStartDateTimeUtc
が欠落しているリクエストを送信すると、対応するフィールドはnull
に設定され、ModelState.IsValid
はに設定されます。 false
およびModelState
には、エラーの説明が含まれます。例: The EndDateTimeUtc field is required.
JsonRequired
属性はJSON.Netに固有です。これは逆シリアル化中に再生されますが、Required
属性(System.ComponentModel.DataAnnotations
名前空間の他の属性として)は、モデルの検証中に、モデルが逆シリアル化された後に再生されます。 JsonRequired
属性に違反した場合、モデルはまったく逆シリアル化されず、対応するアクションパラメーターはnull
に設定されます。
Required
よりもJsonRequired
属性を優先する必要がある主な理由は、JsonRequired
が他のコンテンツタイプ(XMLなど)では機能しないためです。 Required
は、モデルが逆シリアル化された後に適用されるため、ユニバーサルです。
バインディングソースとして[FromBody]
を使用すると、モデルプロパティはデフォルト値を取得し、[BindRequired]
は無視されます。 "パラメータ検証の問題" に関連する問題があります。
この場合、バインディングプロパティを適用するには、[JsonRequired]
の代わりに[BindRequired]
を使用することをお勧めします。
[JsonRequired]
は、シリアル化と逆シリアル化の両方に影響することに注意してください。