diff --git a/aspnetcore/diagnostics/bl0008.md b/aspnetcore/diagnostics/bl0008.md new file mode 100644 index 000000000000..bf4f33a7a33c --- /dev/null +++ b/aspnetcore/diagnostics/bl0008.md @@ -0,0 +1,90 @@ +--- +title: "BL0008: Component parameters should be auto properties" +ai-usage: ai-assisted +description: "Learn about analysis rule BL0008: Component parameters should be auto properties" +author: guardrex +monikerRange: '>= aspnetcore-8.0' +ms.author: wpickett +ms.date: 11/17/2025 +uid: diagnostics/bl0008 +--- +# 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](xref:Microsoft.AspNetCore.Components.SupplyParameterFromFormAttribute) 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: + +> :::no-loc text="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: + +```csharp +[SupplyParameterFromForm] +public InputModel Input { get; set; } = new(); +``` + +The analyzer reports the following warning, where the `{COMPONENT}` placeholder is the component type name: + +> :::no-loc text="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: + +```csharp +[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](xref:blazor/components/lifecycle#component-initialization-oninitializedasync). + +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: + +```razor + + ... + + +@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](xref:blazor/components/lifecycle#component-initialization-oninitializedasync), leaving the property as an [automatically implemented property (*auto property*)](/dotnet/csharp/programming-guide/classes-and-structs/auto-implemented-properties). The following change also makes `Input` a [nullable reference type (NRT)](xref:migration/50-to-60#nullable-reference-types-nrts-and-net-compiler-null-state-static-analysis): + +```csharp +[SupplyParameterFromForm] +private InputModel? Input { get; set; } + +protected override void OnInitialized() => Input ??= new(); +``` + +## When to suppress warnings + +Do not suppress a warning from this rule. diff --git a/aspnetcore/diagnostics/code-analysis.md b/aspnetcore/diagnostics/code-analysis.md index 5e71a9e7dfea..698b7902b6e2 100644 --- a/aspnetcore/diagnostics/code-analysis.md +++ b/aspnetcore/diagnostics/code-analysis.md @@ -50,6 +50,7 @@ Diagnostic ID: * [BL0005](xref:diagnostics/bl0005) * [BL0006](xref:diagnostics/bl0006) * [BL0007](xref:diagnostics/bl0007) +* [BL0008](xref:diagnostics/bl0008) * [MVC1000](xref:diagnostics/mvc1000) * [MVC1001](xref:diagnostics/mvc1001) * [MVC1002](xref:diagnostics/mvc1002) diff --git a/aspnetcore/toc.yml b/aspnetcore/toc.yml index 238eaebc535f..96a9e6b5221e 100644 --- a/aspnetcore/toc.yml +++ b/aspnetcore/toc.yml @@ -1499,6 +1499,8 @@ items: uid: diagnostics/bl0006 - name: BL0007 uid: diagnostics/bl0007 + - name: BL0008 + uid: diagnostics/bl0008 - name: MVC1000 uid: diagnostics/mvc1000 - name: MVC1001