HTML Helpers in ASP.NET MVC 4

3

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

    
asked by anonymous 08.11.2014 / 13:42

3 answers

6

Parameter goal x => x. ...

This parameter is used so that the helper, in LabelFor , knows what is the property of its Model object to which it should render a label. From that moment, LabelFor is able to get the metadata of the indicated property. In case he will be interested in a metadata called DisplayName .

  • Case 1:

     @Html.LabelFor(x => x)
    

    That is to say: render a label for the object Model as a whole. The rule for getting the root model metadata 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 for the MinhaPropriedade property. The LabelFor method knows how to extract this information from the property metadata, one of which is to put the Display(Name = "Label da propriedade)" attribute in the property.

How do LabelFor get display name?

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

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

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

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

  • lambda: This parameter is passed as a lambda, but in fact the type of object that LabelFor receives is Expression<Func<TModel, TValue>> . This type is able to represent the past lambda in the form of a AST (Abstract Syntax Tree) that 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 with the available metadata on the html.ViewData.ModelMetadata object and get the DisplayName .

How does C # to know the lambda type?

C # does this through a type inference process.

We know that the LabelFor method is generic with the types TModel and TValue , and also that it receives 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 has a MinhaProp property of type string :

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

C # knows that 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 the generic types TModel and TValue for the LabelFor method, then C # will have to infer ("guess") what the types are. This is done through the arguments being passed to the method:

  • The argument html is getting the value of Html . This means that HtmlHelper<TModel> is equal to HtmlHelper<MeuModelo> . You can 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 of type Expression<Func<TModel, TValue>> ... but since C # already knows that TModel is equal to MeuModelo , then you can substitute in type of parameter that looks like this:

    Expression<Func<MeuModelo, TValue>>

    This type means "expression that receives MeuModelo and returns TValue " . Now we only need to know what kind of TValue .

    The parameter is receiving x => x.MinhaProp . This lambda receives 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 you can see that x is d type MeuModelo . Therefore, x.MinhaProp is of type string . And finally TValue is of type string .

Type inference is over, with the following conclusions:

  • TModel is type MeuModelo
  • x is of type MeuModelo
  • TValue is type string

And now it's possible to populate generic types of LabelFor :

System.Web.Mvc.Html.LabelExtensions.LabelFor<MeuModelo, string>(Html, x => x.MinhaProp)
    
08.11.2014 / 20:59
1

LabelFor uses your configured Model in the View to render a Label.

Example:

// Model

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

Generate a Label in your View related to your Model's property:

// View

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

The "m" is YourModel. The parameter in m => m.SuaPropriedade is a lambda expression .

html result:

<label for="SuaPropriedade">Propriedade do model</label>
    
08.11.2014 / 14:19
1

The idea here was to give an overview of lambda that is what was used in the referenced parameter. Read the other answers for more complete information about the whole feature, especially Miguel Angelo's.

This is 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 are not running anything, you are just defining what it should do. The code that receives it at the appropriate time will call it as if it were a normal method and at that moment that action will be executed. Executing this is a bit different from a normal call, but this way it's easy for you to understand. This way you pass information in a slightly richer way, you are not simply passing values, you pass a whole structure of data.

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

In the second example, do a little more. The parameter is model but you do not want to use model purely and simply, probably would not, you're getting a member of model . You are getting model.Propriedade and it is the value of this member that will be used in Label .

Lambda may receive other names .

    
08.11.2014 / 15:36