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
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.

@ilonatommy ilonatommy requested a review from javiercn December 11, 2025 09:38
@ilonatommy ilonatommy self-assigned this Dec 11, 2025
@ilonatommy ilonatommy requested a review from oroztocil December 12, 2025 09:29
}
}

public static MemberInfo GetMemberInfo<TValue>(Expression<Func<TValue>> accessor)
Copy link
Member

Choose a reason for hiding this comment

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

I'm just curious, why can't we use FieldIdentifier?

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

4 participants