web-dev-qa-db-ja.com

JSON本体を使用したASP.NETコアモデルバインディングでのRequiredおよびJsonRequiredの使用

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-Typeapplication/jsonに設定され、本文が空のリクエストを送信すると、予想どおり、コントローラーのrequestnullで、ModelState.IsValidfalseです。

しかし、私がこのような体を持っているとき:

{
  "hello": "a-string-value!"
}

私のrequestnullではなく、すべてにデフォルト値があり、ModelState.IsValidtrueです。

もちろん、これはすべてのRequiredプロパティが欠落していて、既存の名前だけがそこのプロパティと一致しないときに発生します(この単一パラメーターのタイプでさえ、stringであり、モデルのどのタイプとも一致しません) 。

したがって、ある意味で、これらのRequired属性は、リクエストに何も含まれていない場合は機能しているように見えますが、リクエストが空でない場合は何もしません。

この質問を準備しているときに、JsonRequired属性もあり、存在するプロパティを処理しているように見えることに気付きました。

では、RequiredJsonRequiredの違いは何ですか?

7
Farzad

Required属性を正しく機能させるには、プロパティをnull許容にする必要があります。

public class MyRequest
{
    [Required]
    public Guid? Id { get; set; }

    [Required]
    public DateTime? EndDateTimeUtc { get; set; }

    [Required]
    public DateTime? StartDateTimeUtc { get; set; }
}

IdEndDateTimeUtc、または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は、モデルが逆シリアル化された後に適用されるため、ユニバーサルです。

12
CodeFuller

バインディングソースとして[FromBody]を使用すると、モデルプロパティはデフォルト値を取得し、[BindRequired]は無視されます。 "パラメータ検証の問題" に関連する問題があります。

この場合、バインディングプロパティを適用するには、[JsonRequired]の代わりに[BindRequired]を使用することをお勧めします。

[JsonRequired]は、シリアル化と逆シリアル化の両方に影響することに注意してください。

0