New rules for Blazor in Meziantou.Analyzer

 
 
  • Gérald Barré

Static analysis is a great way to improve the quality of your code and detect errors before they happen. Blazor has some dynamic parts, so some errors occur only at runtime. In this post, I describe the recent updates in Meziantou.Analyzer to detect some of these errors at compile-time.

Meziantou.Analyzer is a NuGet package that provides a set of analyzers to improve the quality of your C# code. It currently contains 120 rules. In this post, I'll show you a few rules related to Blazor and Razor components.

#How to install Meziantou.Analyzer

Meziantou.Analyzer is available on NuGet. To install the package, you can use the following command:

Shell
dotnet add package Meziantou.Analyzer

This should add the following line to your .csproj file:

MSBuild project file
<PackageReference Include="Meziantou.Analyzer" Version="1.0.742">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>

#Meziantou Analyzer's Rules for Blazor

##Detect unknown component parameters

The MA0115 rule detects unknown component parameters. When you use unknown parameters, Blazor throws an exception at runtime. This is too late and you cannot detect errors or breaking changes when updating a package.

Let's consider a component MyComponent that accepts a Title parameter:

MyComponent.razor (Razor)
<h3>@Title</h3>

@code {
    [Parameter] public string Title { get; set; }
}

If you use this component with an unknown parameter, you'll get a warning:

Sample.razor (Razor)
@* This code compiles, but fails at runtime as "UnknownParameter" does not exist *@
<MyComponent Title="value" UnknownParameter="dummy" />

##Properties marked with [SupplyParameterFromQuery] attribute should also be marked as [Parameter]

The [SupplyParameterFromQuery] attribute specify that a component parameter of a routable component can come from the query string. This attribute must be used in combination with the [Parameter] attribute to be used by Blazor. You can read more about Query Strings in Blazor in this documentation page.

The MA0116 will report a warning if the [Parameter] attribute is missing.

MyComponent.razor (Razor)
@code {
    [SupplyParameterFromQuery] // MA0116: Missing [Parameter] attribute
    public string? Value { get; set; }
}

##Properties marked with [SupplyParameterFromQuery] attribute are only valid in routable components

The [SupplyParameterFromQuery] attribute specify that a component parameter of a routable component can come from the query string. A component is routable when the @page is used in the component or the [Route("")] attribute is used explicitly. You can read more about Query Strings in Blazor in this documentation page.

The MA0122 will report a warning if the component is not routable (@page is not defined).

MyComponent.razor (Razor)
@code {
    [Parameter, SupplyParameterFromQuery] // MA0122: @page is missing
    public string? Value { get; set; }
}

##Properties marked with [EditorRequired] attribute should also be marked as [Parameter]

The [EditorRequired] attribute specifies that a component parameter is mandatory. This attribute must be used in combination with the [Parameter] attribute to be used by Blazor. You can read more about this attribute in this documentation page.

The MA0117 will report a warning if the [Parameter] attribute is missing.

MyComponent.razor (Razor)
@code {
    [EditorRequired] // MA0117: Missing [Parameter] attribute
    public string? Value { get; set; }
}

##Methods marked with [JSInvokable] attribute must be public

Blazor allows to call .NET code from JS. This is done by using the [JSInvokable] attribute. The method you want to call from JS must be public and decorated with [JSinvokable].

The MA0118 reports a warning when a method is marked as [JSInvokable] but is not public.

C#
class Sample
{
    [JSInvokable] // MA0118: The method must be public
    internal static int[] ReturnArray()
    {
        return new int[] { 1, 2, 3 };
    }
}

##JSRuntime must not be used in OnInitialized or OnInitializedAsync

Unless you are using Blazor WebAssembly, the JSRuntime is not accessible in OnInitialized or OnInitializedAsync. If you try to use the JSRuntime in these methods, you'll get an error at runtime. This rule also detects types that use the JSRuntime under the hood, such as ProtectedBrowserStorage.

The MA0119 reports a warning if the JSRuntime is used in the OnInitialize or OnInitializeAsync methods. If Blazor WebAssembly is detected, the rule is disabled.

##Use InvokeVoidAsync instead of InvokeAsync when the return value is not used

The InvokeVoidAsync method is a shortcut to call a JS function without waiting for the result. It is equivalent to calling InvokeAsync and ignoring the result.

The MA0120 rule reports usages of IJSRuntime.InvokeAsync when the returned value is not used.

##Do not overwrite parameter values

Component parameters should not be set manually by the component after the component is rendered for the first time. The documentation explains the reasons for this in the Overwritten parameters section.

The MA0121 rule reports assignments to a parameter outside of the constructor, OnInitialized, and SetParametersAsync.

The rule is disabled by default as it may report false-positives. You need to enable it using an .editorconfig file:

[*.cs]
dotnet_diagnostic.MA0121.severity = warning

#Additional resources

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?Buy Me A Coffee💖 Sponsor on GitHub