【问题标题】:ASP.NET MVC Strongly Typed HTML HelpersASP.NET MVC 强类型 HTML 帮助器
【发布时间】:2012-01-05 05:53:15
【问题描述】:

让我们走这条线:@Html.LabelFor(m => m.UserName) 在带有这一行的页面上:@model CurrencyMvc.Models.RegisterModel

我假设当页面视图呈现时 LabelFor 会自动调用并引用所描述的模型,并且 Lambda 函数会告诉它如何从模型中获取所需的信息?

我不清楚为什么我们在可以传递实际值时传递函数,例如m.用户名。

哦,当这个助手被调用时,“m”是从哪里来的?

【问题讨论】:

    标签: asp.net-mvc-3 lambda strongly-typed-view


    【解决方案1】:

    有 2 个类用于剃须刀页面(第二个派生自第一个):

    1. System.Web.Mvc.WebViewPage
    2. System.Web.Mvc.WebViewPage<T>

    因此,当您通过指定模型使用强类型视图时,您的视图派生自通用版本,Html 属性是通用HtmlHelper<TModel>。由于始终使用强类型视图是一种很好的做法,因此我将不再讨论第一类,因为它没有意义。

    我们看一下LabelFor扩展方法的签名:

    public static MvcHtmlString LabelFor<TModel, TValue>(
        this HtmlHelper<TModel> html, 
        Expression<Func<TModel, TValue>> expression
    )
    {
        ...
    }
    

    从这个定义可以看出,LabelFor 方法是 HtmlHelper&lt;TModel&gt; 类的扩展方法,它接受 1 个参数。此方法仅在您具有强类型视图时可用。该参数表示一个 lambda 表达式,它仅限于成员访问表达式(如果您尝试使用一些花哨的东西,助手将抛出异常)。它将模型作为参数,并且必须返回此模型的属性。

    借助此信息,帮助程序能够确定正在指定的成员的名称,从而生成正确的标记。由于参数是一个 lambda 表达式,它还能够确定该属性的元数据(您可能已经使用 [DisplayName] 等属性修饰了视图模型属性,...允许您指定其他元数据)。如果帮助器只取了你所要求的值:Html.LabelFor(Model.SomeValue),你就会明白在这个LabelFor 方法中你将得到的只是这个值。您将永远无法访问视图模型的元数据,这是 ASP.NET MVC 中的一个基本概念。

    【讨论】:

    • 谢谢你 - 我希望我能给你点赞,但是另一个答案是第一位的,我太新了,无法投票。你的帖子同样有用。再次感谢。
    【解决方案2】:

    我假设当页面视图呈现 LabelFor 被调用 自动参考所描述的模型,并且 Lambda 函数告诉它如何从模型中获取它需要的信息?

    我不完全确定我明白你对这部分的意思,我猜你的意思是@LabelForknows 使用哪个模型?

    是的,如果你看一下syntax,它是这样的:

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

    您可以看到第一个参数以this 开头,这使其成为扩展方法。当您添加行时 @model CurrencyMvc.Models.RegisterModel this HtmlHelper&lt;TModel&gt; 成为您的 RegisterModel。

    我不清楚为什么我们在可以传递的时候传递一个函数 实际值,例如m.用户名。

    大多数情况下,“lambda 表达式”只是一个 Func&lt;T&gt;,但使用剃刀 @Html.xfor(例如 @Html.LabelFor),您会传入一个 Expression&lt;Func&lt;TModel, TValue&gt;&gt;,它是 lambda 表达式的树数据结构。通俗地说;一种未编译的 Func。

    如果您传入m.Username,则该方法将简单地包含“Dale Burrell”。但是例如,html文本框生成为

    <input type="text" name="Username" value="Dale Burrell">
    

    如你所见,它实际上需要m.Username变量名

    哦,当这个助手被调用时,“m”是从哪里来的?

    这只是一个变量。就像foreach(var m in dataset){}“m 是从哪里来的?” ——你编的。你可以用任何东西替换 m

    【讨论】:

    • 好的,我认为这对我来说开始有意义了......这是漫长的一天,有很多新信息。因此,为了澄清,我在这里为了简单起见,我可以将 LabelFor 方法视为在我的 RegisterModel 类上被称为方法(扩展)。然后在 LabelFor 方法中,它使用/调用“表达式”来获取所需的值,并且(大而在这里)还解构“表达式”以计算出该值与类中的哪些属性相关联?因此,要考虑哪些属性、验证等我在正确的轨道上吗?
    • 嗯.. 是的,除了“我的 RegisterModel 上的(扩展)”; this HtmlHelper&lt;TModel&gt; 是 HtmlHelper 的扩展,其中 TModel 是您的模型。在 razor 中,您可以像 @Html 一样使用 HtmlHelper。因此,如果您不将其用作扩展名,则改为使用HtmlHelper(RegisterModel, m =&gt; m.UserName)。 ——但其余的,是的,这听起来是对的。仅用于术语;它不会解构表达式,而是使用 Expression.Compile() 方法对其进行编译。
    • 是的,我想我已经明白了,所以因为它是一个 HtmlHelp 它会从内部引用我的 RegisterModel 实例?所以当我调用 Html.LabelFor() 它知道我的 RegisterModel 对象。 (并且当没有 RegisterModel 存在时,它会创建一个空白?)对不起,如果我对此似乎很愚蠢,只是想在脑海中弄清楚。此外,当我说解构时,我的意思是除了编译 Lambda 表达式之外,它还必须使用表达式树来确定要查询的属性的对象属性,例如[显示(名称)]?
    【解决方案3】:

    我知道已经有一段时间了,但我认为下面的链接对于那些仍在寻找一个好的解释的人来说会很有帮助。 http://odetocode.com/blogs/scott/archive/2012/11/26/why-all-the-lambdas.aspx

    【讨论】:

      猜你喜欢
      • 2011-03-18
      • 1970-01-01
      • 1970-01-01
      • 2011-04-06
      • 2014-06-04
      • 1970-01-01
      • 1970-01-01
      • 2017-09-28
      • 2012-09-15
      相关资源
      最近更新 更多