dotnet/aspnetcore · error · ArgumentException

The value must implement {nameof(IComponent)}.

Error message

The value must implement {nameof(IComponent)}.

What it means

RouteData's constructor enforces that the page type it carries is a Blazor component (implements IComponent), because RouteView will later instantiate and render it through the component pipeline. Passing a non-component type (a plain class, a model, a controller) would fail later with a less clear cast, so the constructor throws ArgumentException at the boundary. The parameter is annotated with [DynamicallyAccessedMembers(Component)] for trim safety.

Source

Thrown at src/Components/Components/src/Routing/RouteData.cs:26

/// <summary>
/// Describes information determined during routing that specifies
/// the page to be displayed.
/// </summary>
public sealed class RouteData
{
    /// <summary>
    /// Constructs an instance of <see cref="RouteData"/>.
    /// </summary>
    /// <param name="pageType">The type of the page matching the route, which must implement <see cref="IComponent"/>.</param>
    /// <param name="routeValues">The route parameter values extracted from the matched route.</param>
    public RouteData([DynamicallyAccessedMembers(Component)] Type pageType, IReadOnlyDictionary<string, object?> routeValues)
    {
        ArgumentNullException.ThrowIfNull(pageType);

        if (!typeof(IComponent).IsAssignableFrom(pageType))
        {
            throw new ArgumentException($"The value must implement {nameof(IComponent)}.", nameof(pageType));
        }

        PageType = pageType;
        RouteValues = routeValues ?? throw new ArgumentNullException(nameof(routeValues));
    }

    /// <summary>
    /// Gets the type of the page matching the route.
    /// </summary>
    [DynamicallyAccessedMembers(Component)]
    public Type PageType { get; }

    /// <summary>
    /// Gets route parameter values extracted from the matched route.
    /// </summary>
    public IReadOnlyDictionary<string, object?> RouteValues { get; }

    /// <summary>

View on GitHub (pinned to 3600ca084e)

Solutions

  1. Verify the type passed as pageType implements IComponent (typical pages are Razor components with @page or a [Route] attribute).
  2. Filter candidate types with typeof(IComponent).IsAssignableFrom(t) before constructing RouteData.
  3. If you have a non-component handler, wrap it in a Razor component instead.
  4. Check that DI and assembly scanning did not pick up a model or interface type as a route handler.

Example fix

// before
var routeData = new RouteData(typeof(UserProfileViewModel), values); // ViewModel is not a component
// after
var routeData = new RouteData(typeof(UserProfile), values); // UserProfile.razor implements IComponent
Defensive patterns

Strategy: type-guard

Validate before calling

// Filter candidate page types before constructing RouteData.
if (!typeof(IComponent).IsAssignableFrom(pageType))
    throw new ArgumentException($"{pageType} is not a Blazor component.", nameof(pageType));
var data = new RouteData(pageType, routeValues);

Type guard

static bool IsComponentType(Type? t) => t is not null && typeof(IComponent).IsAssignableFrom(t);

Prevention

When it happens

Trigger: Constructing new RouteData(typeof(SomeNonComponentType), routeValues) where the type does not implement IComponent. Common when route data is built from reflection over arbitrary types or when a page type is mistakenly replaced with a view-model.

Common situations: Custom routing code that maps URL patterns to handler types without filtering by IComponent; refactoring a page class into a non-component base type; passing a model type instead of its bound component; testing RouteData with stub types.

Related errors


AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11). Data as JSON: /api/errors/b67395552f2f293b. Report an issue: GitHub.