@Html.EditorFor(m => m) lambda syntax in MVC
Asked Answered
C

4

13

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

Cingulum answered 6/5, 2012 at 0:15 Comment(2)
"and don't see any overload for passing in just a single parameter" -- EditorFor is an extension method, so you're looking for the one overload with two parameters, the first being "this".Solomon
Also one thing that I'd recommend from building a site in mvc3 is to use the specific types of editors like @Html.TextBoxFor(m => m.name) this is so that if you ever want a default value it will work. Where I (at least) have not been able to assign this to an EditorFor. Also TextBox/TextArea etc support placeholders among other things where EditorFor does not. so you could do @Html.TextBoxFor(m=>m.Name, new { placeholder = "John Doe" }) and mvc will automatically implement a placeholder in browsers that support it.Pitts
V
18

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

Vaccinate answered 6/5, 2012 at 0:29 Comment(1)
wow, awesome answer! The part I was missing is that you have to use an expression that is a method name that returns a model. Your example with MyStaticClass was most helpful in understanding that concept.Cingulum
R
3
  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.

Rasorial answered 6/5, 2012 at 0:27 Comment(1)
3. Very helpful, I didn't notice/realize it was passing "this" as the first parameter. 2. I'm still a little mystified by this lambda function, since combined with Kirk Woll's answer, it should be returning a type of modelCingulum
F
2

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.

Fribble answered 6/5, 2012 at 0:29 Comment(0)
F
1

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.

Florous answered 6/5, 2012 at 0:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.