Skip to content

Conversation

@ilonatommy
Copy link
Member

@ilonatommy ilonatommy commented Dec 3, 2025

Summary

This PR adds the DisplayName<TValue> component to enable displaying property display names from [Display] and [DisplayName] attributes in Blazor applications, addressing the feature gap identified in issue #49147.

Background

Blazor currently lacks a built-in mechanism to display property names from metadata attributes like MVC's @Html.DisplayNameFor() helper. This forces developers to either:

  • Hardcode label text (violating DRY principles and making localization difficult)
  • Build custom reflection-based solutions
  • Duplicate display name information across models and views

The new DisplayName<TValue> component provides an attribute-based solution that follows the same familiar pattern as other Blazor form components like ValidationMessage<TValue>.

Fixes #49147

Changes

Public API

namespace Microsoft.AspNetCore.Components.Forms;

public class DisplayName<TValue> : ComponentBase
{
    [Parameter]
    [EditorRequired]
    public Expression<Func<TValue>>? For { get; set; }
}

Implementation Details

The component extracts the property name from the expression and reads display metadata:

  1. First checks for DisplayAttribute.Name (System.ComponentModel.DataAnnotations)
  2. Falls back to DisplayNameAttribute.DisplayName (System.ComponentModel)
  3. Uses the property name itself if no attributes are present

Tests

Unit tests in src/Components/Web/test/Forms/DisplayNameTest.cs:

  • ✅ Throws when For parameter is missing
  • ✅ Reads DisplayAttribute.Name correctly
  • ✅ Reads DisplayNameAttribute.DisplayName correctly
  • DisplayAttribute takes precedence over DisplayNameAttribute
  • ✅ Falls back to property name when no attributes present
  • ✅ Works with different property types (string, decimal, DateTime, int)

E2E test in src/Components/test/E2ETest/Tests/FormsTest.cs:

  • DisplayNamelReadsAttributesCorrectly() - Verifies the component renders correctly in a browser with all attribute scenarios

API usage

Basic form usage:

<EditForm Model="@product">
    <div class="mb-3">
        <label class="form-label">
            <DisplayName For="@(() => product.Name)" />
        </label>
        <InputText @bind-Value="product.Name" class="form-control" />
        <ValidationMessage For="@(() => product.Name)" />
    </div>
</EditForm>

Table headers:

<table class="table">
    <thead>
        <tr>
            <th><DisplayName For="@(() => product.Name)" /></th>
            <th><DisplayName For="@(() => product.Price)" /></th>
            <th><DisplayName For="@(() => product.ReleaseDate)" /></th>
        </tr>
    </thead>
</table>

Model example:

public class Product
{
    [Display(Name = "Product Name")]
    public string Name { get; set; }
    
    [DisplayName("Unit Price")]
    public decimal Price { get; set; }
    
    [Display(Name = "Release Date")]
    public DateTime ReleaseDate { get; set; }
}

Copilot AI review requested due to automatic review settings December 3, 2025 15:34
@ilonatommy ilonatommy requested a review from a team as a code owner December 3, 2025 15:34
@ilonatommy ilonatommy added the area-blazor Includes: Blazor, Razor Components label Dec 3, 2025
@ilonatommy ilonatommy added this to the .NET 11 Planning milestone Dec 3, 2025
Copilot finished reviewing on behalf of ilonatommy December 3, 2025 15:38
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces the DisplayNameLabel<TValue> component to display property display names from metadata attributes ([Display] and [DisplayName]), providing Blazor with functionality similar to MVC's @Html.DisplayNameFor() helper. The component addresses a feature gap that previously required developers to hardcode labels or build custom reflection-based solutions.

Key Changes:

  • New DisplayNameLabel<TValue> component that extracts and displays property names from metadata attributes
  • Comprehensive unit tests covering attribute precedence, fallback behavior, and various property types
  • E2E test validating browser rendering with real-world scenarios

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/Components/Web/src/Forms/DisplayNameLabel.cs Core component implementation with expression parsing and attribute reading logic
src/Components/Web/test/Forms/DisplayNameLabelTest.cs Unit tests covering attribute precedence, type support, and error handling
src/Components/test/E2ETest/Tests/FormsTest.cs Browser-based integration test verifying component rendering
src/Components/test/testassets/BasicTestApp/FormsTest/DisplayNameLabelComponent.razor Test component demonstrating all attribute scenarios
src/Components/test/testassets/BasicTestApp/Index.razor Navigation entry for the test component
src/Components/Web/src/PublicAPI.Unshipped.txt Public API surface additions

@campersau
Copy link
Contributor

The name DisplayNameLabel might be missleading. I thought it would render a <label> but it only renders the plain name.

Copy link
Member

@javiercn javiercn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to ensure localization works with this component.

@ilonatommy
Copy link
Member Author

We need to ensure localization works with this component.

Added tests + tested multiple localizing resources manually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-blazor Includes: Blazor, Razor Components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DisplayNameFor support in Blazor

3 participants