Edit

Share via


BL0008: Component parameters should be auto properties

Value
Rule ID BL0008
Category Usage
Fix is breaking or non-breaking Non-breaking

Cause

A property has the [SupplyParameterFromForm] attribute and is initialized with a non-default property initializer.

Rule description

The property initializer can be overwritten with null during form submission, causing the EditForm to fail with the following exception:

InvalidOperationException: EditForm requires either a Model parameter, or an EditContext parameter, please provide one of these.

The analyzer warns developers when this pattern is detected, while safely ignoring default value initializers (null, null!, default, default!) that don't cause the same issue.

Consider the following Input form model with a property initializer:

[SupplyParameterFromForm]
public InputModel Input { get; set; } = new();

The analyzer reports the following warning, where the {COMPONENT} placeholder is the component type name:

Property '{COMPONENT}.Input' has [SupplyParameterFromForm] and a property initializer. This can be overwritten with null during form posts.

Safe patterns that are ignored by analyzer:

[SupplyParameterFromForm]
public InputModel Input { get; set; } = default!;

[SupplyParameterFromForm]
public InputModel Input { get; set; } = null!;

How to fix violations

To ensure the initialized value isn't overwritten, move the initialization to one of the OnInitialized{Async} lifecycle methods.

Consider the following Razor component that generates a BL0008 code analysis warning because the Input model for the form is decorated with [SupplyParameterFromForm] and has a property initializer:

<EditForm Model="Input" OnSubmit="Submit" FormName="Starship1">
    ...
</EditForm>

@code {
    [SupplyParameterFromForm]
    private InputModel Input { get; set; } = new();

    private void Submit()
    {
        ...
    }

    public class InputModel
    {
        public string? Id { get; set; }
    }
}

To fix the violation, the initialization code for the Input property is moved to the OnInitialized lifecycle method, leaving the property as an automatically implemented property (auto property). The following change also makes Input a nullable reference type (NRT):

[SupplyParameterFromForm]
private InputModel? Input { get; set; }

protected override void OnInitialized() => Input ??= new();

When to suppress warnings

Do not suppress a warning from this rule.