How to use reflection in ASP.NET MVC with razor/cshtml?

Dean Marinov 20 Reputation points
2024-07-21T18:10:17.09+00:00

Why are the property names displayed 'correctly' in the input tag but not in the label tag?

And why are they pre-typed in the input-fields in HTML? f.e.: every label = name

and every input field is the property name, where it should be empty.

grafik

                @foreach (var property in typeof(Person).GetProperties())
                {
                    <label asp-for="@property.Name" class="control-label"></label>
                    <input asp-for="@property.Name" class="form-control" />                    
                }
ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,553 questions
0 comments No comments
{count} votes

Accepted answer
  1. Ping Ni-MSFT 4,335 Reputation points Microsoft Vendor
    2024-07-22T03:22:07.8833333+00:00

    Hi @Dean Marinov,

    The InputTagHelper helps us to write code in a style of declarative programming. When you find it difficult to render different fields dynamically by reflection, feel free to use the @Html.Xyz equivalent in a programmatic way:

    @model Person
    <form>
        @foreach (var property in typeof(Person).GetProperties())
        {       
            <div class="form-group">
                @Html.Label(@property.Name)
                @Html.Editor(@property.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessage(@property.Name, new { htmlAttributes = new { @class = "text-danger" } })
            </div>
        }
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>
    

    Or you can manually set the value for label and change the input tag helper like below. Due to the @property.Name contains the value so that it will display the value. You need get the property real value and set to asp-for. Then for model binding, be sure manually add the name attribute. id attribute is optional by yourself.

    @model Person
    <form>
        @foreach (var property in typeof(Person).GetProperties())
        {
            var propValue = @property.GetValue(@Model, null);
            <div class="form-group">
                <label asp-for="@property.Name" class="control-label">@property.Name</label>
                <input asp-for="@propValue" name="@property.Name" id="@property.Name" class="form-control" />
            </div>
        }
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>
    

    Feel free to choose each one you like to achieve your requirement.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,

    Rena

    1 person found this answer helpful.
    0 comments No comments

2 additional answers

Sort by: Most helpful
  1. SurferOnWww 2,816 Reputation points
    2024-07-22T02:02:58.0866667+00:00

    Why are the property names displayed 'correctly' in the input tag but not in the label tag? And why are they pre-typed in the input-fields in HTML?

    @foreach (var property in typeof(Person).GetProperties())

    The "property" in the above code is System.Reflection.PropertyInfo class which has Name property. See the following for the "property" of LastName property of Person class:

    enter image description here

    Therefore, the label tag helper <label asp-for="@property.Name"> uses the property name "Name" of PropertyInfo object and input tag helper <input asp-for="@property.Name"> uses the value of Name property of PropertyInfo object.


    Additional Answer on 2024/7/23

    You will have to follow standard practice to use Tag helpers if you need validation of user input at the client side.

    For example,

    Model

    Add the RequredAttribute to the BirthDay property for validation:

    public class Person
    {
        public string? Name { get; set; }
        public string? LastName { get; set; }
    
        [Required(ErrorMessage = "BirthDay is required")]
        public DateTime BirthDay { get; set; }
    
        public string? Street { get; set; }
    }
    

    View

    Follow standard practice to use Tag Helpers:

    @model MvcApp.Model.Person
    
    <label asp-for="Name"></label>
    <input asp-for="Name" />
    
    <label asp-for="LastName"></label>
    <input asp-for="LastName" />
    
    <label asp-for="BirthDay"></label>
    <input asp-for="BirthDay" />
    
    <label asp-for="Street"></label>
    <input asp-for="Street" />
    

    Resultant html code

    See the input tag for the BirthDay which has the validation attribute data-val-required="BirthDay is required":

    <label for="Name">Name</label>
    <input type="text" id="Name" name="Name" value="" />
    
    <label for="LastName">LastName</label>
    <input type="text" id="LastName" name="LastName" value="" />
    
    <label for="BirthDay">BirthDay</label>
    <input type="datetime-local" data-val="true" data-val-required="BirthDay is required" id="BirthDay" name="BirthDay" value="" />
    <input name="__Invariant" type="hidden" value="BirthDay" />
    
    <label for="Street">Street</label>
    <input type="text" id="Street" name="Street" value="" />
    

    If you use the Html helpers, like below;

    @foreach (var property in typeof(Person).GetProperties())
    {
        <label asp-for="@property.Name"></label>
        <input asp-for="@property.Name" />
    }
    

    it will result in the following html code;

    <label for="Name">Name</label>
    <input class="text-box single-line" id="Name" name="Name" type="text" value="" />
    
    <label for="LastName">LastName</label>
    <input class="text-box single-line" id="LastName" name="LastName" type="text" value="" />
    
    <label for="BirthDay">BirthDay</label>
    <input class="text-box single-line" id="BirthDay" name="BirthDay" type="datetime-local" value="" />
    
    <label for="Street">Street</label>
    <input class="text-box single-line" id="Street" name="Street" type="text" value="" />
    <hr />
    

    in which there is no validation attribute.

    1 person found this answer helpful.
    0 comments No comments

  2. Dean Marinov 20 Reputation points
    2024-07-22T14:34:10.89+00:00

    Thank you both! Both replies were on point!


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.