HTML Helpers in ASP.NET MVC 4

Asked

Viewed 936 times

3

I saw some HTML Helpers like this: @Html.LabelFor(x => x) and @Html.LabelFor(model => model.Propriedade), however, I do not understand this parameter that I must pass, x => x, what is this?

  • Got it, but where does Displayname come into it? The result in HTML shouldn’t be: <label for="Your property">Model property</label>?

  • I added an answer showing how the LabelFor reaches up to the DisplayName of the property indicated by lambda. If there is any doubt just talk! Abç

  • I still don’t understand the use of lambda, for me, it would make more sense like this: @Html.Labelfor(Model.Property)

  • This way, you would be passing the value of the property to the helper. Imagine that there is this property in the model class: [Display(Name="Nome da pessoa")] public string Name { get; set; }, with the value "Miguel Angelo" attributed to her... If it were the way you said, there would be no difference between @Html.LabelFor(Model.Name) and @Html.LabelFor("Miguel Angelo"). It is not the value of property that we want to pass on, but something that is able to identify of what property get the DisplayName, which is information given through the attribute Display: "Nome da pessoa".

  • I was able to understand the result of this, but I can’t understand the lambda syntax, which means x => x.Property, why X? why not Y? How does C# recognize X as the Model?

  • The variable name, you invent. It can be x, y, m, model... anything. C# knows the type, because it is able to "guess" through a type inference process. I’ll edit my reply showing how C# does it step by step.

  • @Take a look at [tour]. You can accept an answer if it solved your problem. You can vote for all the posts on the site as well. Did any help you more? You need something to be improved?

Show 2 more comments

3 answers

6

Purpose of the parâmtero x => x....

This parameter is used so that the helper, in the case LabelFor know what is the property of your object Model for which it must render a label. From that moment on, LabelFor is able to obtain the metadata of the specified property. In case it will be interested in a metadata called DisplayName.

  • case 1:

     @Html.LabelFor(x => x)
    

    This means: render a label to the object Model as a whole. The rule for obtaining metadata from the root model depends on a rendering hierarchy. This form is most common within Editor Templates and Display Templates, because within the templates this hierarchy is available.

  • case 2:

     @Html.LabelFor(x => x.MinhaPropriedade)
    

    This means: render a label to the property MinhaPropriedade. The method LabelFor knows how to extract this information from the property metadata, one of the ways is to place the attribute Display(Name = "Label da propriedade)" on the property.

Like the LabelFor get the display name?

Now that I have explained the purpose of lambda being passed to the helper, I will explain how a helper works to get to the metadata of the property in question.

The helper, when called, will have access to the object HtmlHelper<TModel>, and lambda passed per parameter. Here is the definition of the method LabelFor:

public static MvcHtmlString LabelFor<TModel, TValue>(
    this HtmlHelper<TModel> html,
    Expression<Func<TModel, TValue>> expression)
  • HtmlHelper<TModel>: that object is the Html (of expression @Html....) on which the Extension-method LabelFor is being applied (for any other html-helper). This is a generic object, where TModel is the type of model being used by view.

    This object has in its structure, all the metadata of the model being worked: html.ViewData.ModelMetadata.

  • lambda: this parameter is passed as a lambda, but actually the type of the object that the LabelFor receives is Expression<Func<TModel, TValue>>. This guy is able to represent the lambda passed in the form of a AST (Abstract Syntax Tree) which will contain in its structure the property must be used in the form of a PropertyInfo (Reflection). From there, the helper is able to associate the PropertyInfo the available metadata in the object html.ViewData.ModelMetadata and get the DisplayName.

How does C# know the type of lambda?

C# does this through a type inference process.

We know the method LabelFor is generic with the types TModel and TValue, and also that it gets two arguments, both using these generic types:

  • this HtmlHelper<TModel> html

  • Expression<Func<TModel, TValue>> expression

Imagine the following view containing cshtml, whose model type is MeuModelo and own a property MinhaProp of the kind string:

@model MeuModelo
@Html.LabelFor(x => x.MinhaProp)

C#, you know that the LabelFor is an extension method, and will translate the method call to:

System.Web.Mvc.Html.LabelExtensions.LabelFor(Html, x => x.MinhaProp)

As the above code does not define generic types TModel and TValue for the method LabelFor, then C# will have to infer ("guess") which are the types. This is done through the arguments being passed to the method:

  • The argument html is receiving the value of Html. Does that mean that HtmlHelper<TModel> is equal to HtmlHelper<MeuModelo>. It is possible to see that TModel has to be MeuModelo.

    parâmetro      |  html  |  HtmlHelper<TModel>
    valor passado  |  Html  |  HtmlHelper<MeuModelo>
    
    conclusão: TModel = MeuModelo
    
  • The argument expression is the type Expression<Func<TModel, TValue>>... just like C# already knows that TModel is equal to MeuModelo, then you can replace in the type of parameter that looks like this:

    Expression<Func<MeuModelo, TValue>>

    That guy means "expression it receives MeuModelo and returns TValue". Now we just need to know what kind of TValue.

    The parameter is receiving x => x.MinhaProp. That lambda gets x and returns x.MinhaProp. Then it is possible to construct the following table to analyze the types:

              |  Expression<Func<MeuModelo, TValue>>  |  x => x.MinhaProp
    ----------+---------------------------------------+---------------------
      recebe  |              MeuModelo                |     x
      retorna |              TValue                   |     x.MinhaProp
    

    In the first line it is possible to see that x type MeuModelo. So, x.MinhaProp is the type string. And finally TValue is the type string.

The inference of types ended with the following conclusions:

  • TModel is the guy MeuModelo
  • x is the type MeuModelo
  • TValue is the guy string

And now it is possible to fill in the generic types of LabelFor:

System.Web.Mvc.Html.LabelExtensions.LabelFor<MeuModelo, string>(Html, x => x.MinhaProp)
  • Got it. Thanks for your help.

1

Labelfor uses its configured Model in the View to render a Label.

Example:

// Model

public class SeuModel
{
    [DisplayName("Propriedade do model")]
    public string SuaPropriedade { get; set; }
}

Generates a Label in your View related to your Model property:

// View

@model SeuModel
@Html.LabelFor(m => m.SuaPropriedade) 

"m" is the Seumodel. The form parameter m => m.SuaPropriedade is a lambda expression.

Result in html:

<label for="SuaPropriedade">Propriedade do model</label>

1

The idea here was to give a general idea about lambda that which was used in that parameter. Read the other answers for more complete information about the entire feature, especially Miguel Angelo’s.

That’s called lambda. See the C# documentation on the subject. It is an unnamed function that is used as an expression. It is a way of passing actions that must be performed by some other algorithm at any given time. This way when you declare the lambda You’re not running anything, you’re just defining what she should do. The code it receives at the appropriate time will call it as if it were a normal method and at this point that action will be executed. The exact execution of this is somewhat different from a normal call, but this way it becomes easy for you to understand. This way you pass information in a slightly richer way, you’re not simply passing values, you pass a whole data structure.

In this case you are saying that you are simply taking the parameter x that the lambda is receiving and using this value as Label in that place. This x will receive a value passed by engine of ASP.Net MVC. He knows what to go through and he knows when to use it, he just doesn’t know what to do with this information before using it. In case neither is doing anything important but could perform a lot of things with it.

In the second example already does a little more. The parameter is model but you don’t want to use the model purely and simply, probably wouldn’t even, you’re picking up a member of model. You’re getting model.Propriedade and it is the value of this member that will be used in the Label.

Lambda can receive other names.

  • In C#, a lambda can be converted into two things: Delegate or Expression<TDelegate>. His explanation considers the first case, and is fully valid to understand both. It occurs that LabelFor (of ASP.NET MVC) if using the second case, in which the lambda is converted into an AST, from which metadata can be extracted (e.g. label, if required, format, etc.), where x is the type of the model itself, which is defined by the user within the view file. P.S. I hate to be critical, especially of someone who helps so much! Plus, I liked the reference to the mathematical origin of the Amblas.

  • @Miguelangelo you are right, I gave an improved one. You must be critical, this is quality and not defect. Anyway I’ll leave more as a complement, yours is much better for the context.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.