S6964 — Value type property used as input in a controller action should be nullable, required or annotated with the JsonRequiredAttribute to avoid under-posting.

Language
C#
Type
Code smell
Severity
Major
Tags
asp.net

Why is this an issue?

When a request omits a non-nullable value-type property, it can receive its default value, such as 0 for an int. The handler then cannot distinguish missing input from an explicit zero. Make the property nullable when absence is allowed, or require its presence with validation supported by your input format and serializer.

For example, {} and {"quantity": 0} both produce Quantity == 0 with the model below. This is called under-posting.

How to fix it

For a required value, one option is a nullable property with [Required]. Missing input remains null, which fails model validation. The example assumes an ASP.NET Core controller receiving the model with [FromBody] and running model validation. With [ApiController], an invalid model normally produces an automatic HTTP 400 response; otherwise, check ModelState.IsValid before using the input.

Code examples

Noncompliant code example


public class OrderRequest
{
    public int Quantity { get; set; } // Noncompliant: omitted input becomes zero
}

Compliant solution


using System.ComponentModel.DataAnnotations;

public class OrderRequest
{
    [Required]
    public int? Quantity { get; set; }
}

This correction rejects both omission and explicit null, while accepting zero. Add value validation if zero is not a valid quantity.

Choose the input contract

required also affects C# object initialization; it is not a general HTTP validation mechanism. JSON attributes apply to the corresponding serializer, not to form or query model binding. When using Newtonsoft.Json, use its own required-property settings and distinguish required presence from whether null is allowed.

If an omitted property intentionally means its default value, document that API contract. A detection exception is not evidence that incoming data has been validated.

Non-reporting cases

This rule does not raise an issue when properties are decorated with the following attributes:

Additionally, this rule does not raise for properties in model classes that are not in the same project as the Controller class that references them. This is due to a limitation of Roslyn (see here).

Some attributes above skip validation or binding rather than require input. In particular, do not add [ValidateNever], [BindNever], or an ignore attribute merely to silence the issue. Test omitted input, explicit null, the default value, and valid values against the endpoint’s actual input format.

Resources

Documentation

↑ Back to top