Question

I'm just learning C# and MVC, and trying to understand some examples.

@Html.EditorFor(m => m)

Eventually I figured out that '=>' is the lambda operator, and that it means something like "m such that m". That doesn't really make any sense to me. Why not just pass in m?

Also, I don't see m defined in any view that I'm working with. Model is defined, and allegedly that's what this method is picking up. How does that work?

Finally, I looked at the definition for Html.EditorFor, and don't see any overload for passing in just a single parameter. Where is this syntax defined?? http://msdn.microsoft.com/en-us/library/ee834942.aspx

Was it helpful?

Solution

Let's break this down by examining the method signature:

MvcHtmlString EditorFor<TModel, TValue>(
    this HtmlHelper<TModel> html, 
    Expression<Func<TModel, TValue>> expression
)

This is using extension method syntax, which means it's adding a method named EditorFor to HtmlHelper such that you can make the call Html.EditorFor. But what we're really interested in is the second parameter, Expression<Func<TModel, TValue>>. That's a pretty complicated parameter, but for now we can ignore the fact that it's an Expression. So simplifying, let's examine:

Func<TModel, TValue> expression

This means that the argument is any method that has one parameter (of type TModel) and the return type is TValue. You've been using lambdas, which is (essentially) a more concise representation of a method, but it's helpful to just think of it as an ordinary method. So you're lambda is taking a model and returning a model:

m => m

That's not as interesting, so let's compare it to a more realistic scenario where you're returning a property off the model:

m => m.MyStringProperty

Now let's compare it with an ordinary static method you've declared somewhere:

public static class MyStaticClass 
{
    public static string Foo(TModel model) 
    {
        return model.MyStringProperty;
    }
}

Although really here it wouldn't be TModel -- it would be whatever you declared your model type via @model. Now, for the sake of discussion, you could have instead used this method in your invocation of EditorFor:

Html.EditorFor(MyStaticClass.Foo);

So to sum up, lambdas are (for the most part) just a short hand for a regular method. So all you're doing is passing methods around.

The last note here is that we are actually using expression trees, which means you aren't actually passing the method, you're passing an object model (an expression tree) that represents the code of the method. This is, essentially, just used to figure out the property name you're using (because usually the lambda would be more like m => m.MyProperty, not merely m => m). This is all to avoid magic strings where you refer to the property name by using a string (i.e. "MyProperty").

OTHER TIPS

  1. In your example, the lambda function doesn't serve any purpose, true. But its real use is for when you want to render the editor for a property of the model: @Html.EditorFor(m => m.SomeProperty). Lambda expressions are really just shorthand for functions, but strongly typed by way of delegates. The concept might be more familiar from Javascript:

    myFunction( function(x) { return x.SomeProperty; });

  2. The "m" isn't predefined. It's naming the parameter for the second part of the lambda expression, and could be anything: @Html.EditorFor( whatever => whatever ). (It refers to the same thing, in this case the page's model, regardless of what you name it.)

  3. The first parameter you see in those definitions for Html.EditorFor isn't really a parameter. You'll notice they're using the this keyword to define extension methods. That parameter refers the the object that invoked the method, in this case the HtmlHelper<Model> object.

1.

  • @Html.EditorFor(m => m) - display editor for whole model
  • @Html.EditorFor(m => m.propertyName) - display editor for specific property of model

2.

@Html.EditorFor(m => m) is equal to @Html.EditorFor(t => t) or @Html.EditorFor(randomName => randomName). Name doesn't matter, it is just parameter's name. The type for this parameter is type of view model.

You have to pass function, because it is not only value, that counts. Reflections are used to get attributes, that describe how to display property. Look at this example

public class ResetPasswordModel
{
    public string Username { get; set; }

    [DataType(DataType.Password)]
    public string NewPassword { get; set; }
    [DataType(DataType.Password)]
    public string PasswordConfirmed { get; set; }
}

Attributes describe, that NewPassword should be password field, not regular input. If we passed value, that would not be possible.

In our example @Html.EditorFor(m => m) will show for containing one input for user name and two password inputs for passwords. @Html.EditorFor(m => m.NewPassword) will show input, which has type of password.

3.

http://msdn.microsoft.com/en-us/library/ee402949.aspx

public static MvcHtmlString EditorFor<TModel, TValue>(
    this HtmlHelper<TModel> html,
    Expression<Func<TModel, TValue>> expression
)

This is extension method for HtmlHelper class. this HtmlHelper<TModel> html is not a parameter, it is type of class, that function extends.

Think of the => operator as meaning "goes to", so (m => m) means "m goes to m", another way of saying you get back the same thing m.

In your example, @Html.EditorFor(m => m), m is an anonymous input parameter to the lambda expression m => m, which is an argument of the extension method EditorFor. As you noted in your question, none of the overloads for this method take less than a single parameter; this is because it is an Extension Method and the first parameter indicates the type it extends. The second parameter is an Expression, and you can use lambda expressions for these.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top