ASP.Net MVC 视图中的这段代码如何通知服务器如何使用模型的属性? link 是什么?
ASP.Net MVC How does this code in the view inform the server how to use the model's properties? What's the link?
我正在学习 MVC,而且我有 WebForms 背景。
我正在使用默认的 MVC 项目模板,但我不明白文本框如何知道设置模型的 "Email" 属性。
login.cshtml
<div class="form-group">
@Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Email, "", new { @class = "text-danger" })
</div>
</div>
所以我知道 m => m.Email
是一个创建 Func<LoginViewModel, string>
匿名函数(或表达式?)的 lambda 表达式。对我来说,它看起来像一个 getter 函数(用于从数据中呈现 html 文本框值),它接受一个视图模型和 returns 一个字符串,通过访问它是 "Email" 属性.
然而服务器以某种方式知道 "m.Email" 变量的所有信息。它知道所有属性,并且知道在将其发布到服务器时使用文本框中的值对其进行设置。
我的问题是它怎么知道的?服务器如何提取有关 "Email" modelview 变量的信息,你能给我一个例子,说明我如何在给定类似 Func<LoginViewModel, string>
类型的情况下手动执行此操作吗?
恭喜您投身于 Mvc。
lambda 函数仅用于创建文本框 html 字符串,它与它返回无关,它使用它来扫描 属性 的数据注释以进行验证,显示表单等等等等
将数据重新用于您的操作?这取决于模型活页夹。
对控制器的任何 post 操作都将由模型绑定器检查其参数,然后将针对所有参数尝试表单集合键以尝试按名称匹配它们。
所以如果你有这样的行为
public ActionResult SendMeData(string firstName)
将扫描表单集合以查找匹配名字(不区分大小写)的键,如果匹配,它将为其设置参数。
在这个动作签名的情况下
public ActionResult SendMeData(Dude dude)
public class Dude {
public string FirstName {get;set;}
}
它将检查 Dude 是否具有无参数构造函数,如果有,它将创建该对象的新实例,然后扫描其属性以在表单集合中查找匹配的名称并进行适当设置。
因此,您想要在 post 操作中发送回控制器的任何值,只需创建一个名称与 属性 或您想要的参数相匹配的 input/select/textarea,然后所有的魔法都为你处理。
这里发生了很多事情。其中一些是由幕后的 Razor 渲染引擎 "hidden" 提供的。例如,当您在页面顶部指定 @model Foo
时,这实际上是为使用 Foo 作为模型类型的页面创建 class 的语法快捷方式。在 WebForms 中,它看起来像这样:
<% @Page Inherits="System.Web.Mvc.ViewPage<Foo>" %>
不过,Razor 向您隐藏了这一点。实际上,当您使用 @model Foo
时,您的视图实际上是 ViewPage<Foo>
现在,如果您查看文档中的 ViewPage:
https://msdn.microsoft.com/en-us/library/dd470798(v=vs.118).aspx
你会看到很多有趣的东西。其中就有Html属性.
这是 HtmlHelper<TModel>
类型,如果您的模型是 Foo,则 TModel 是 Foo。
因此,当您(在 Razor 中)编写 @Html.Whatever()
这实际上是一个 HtmlHeler<Foo>.Whatever()
。
https://msdn.microsoft.com/en-us/library/dd492619(v=vs.118).aspx
现在,让我们看看您关心的实际方法。 Html.TextBoxFor()
如果你看上面的linkHtmlHelper,你可以看到上面有很多扩展方法,这些扩展方法是HtmlHelpers的基础MVC 提供。其中有:
https://msdn.microsoft.com/en-us/library/ee703644(v=vs.118).aspx
public static MvcHtmlString TextBoxFor<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression
)
到这里,我们可以看出这是一个扩展方法。它采用TModel 和TProperty 通用参数,并且在函数参数中是this HtmlHelper<TModel> htmlHelper
作为第一个参数。 C# 在扩展方法中对您隐藏了它,但在您调用它时将其传递给方法 @Html.TextBoxFor()
。
请注意,下一个参数是表达式,类型为 Expression<Func<TModel, TProperty>>
,因此,这就是表达式(或 lambda)最终知道模型是什么,并知道 return 的方式属性 类型。它归结为在页面顶部指定模型类型,并使这个气泡向下穿过对象图。
我知道这需要吸收很多东西,但是如果您跟踪对象链,您应该了解它是如何工作的。
至于回传到服务器,这跟这没什么关系。这是模型绑定系统的一部分,它只查看发布到服务器的值和操作方法采用的参数类型,然后尝试根据它们的名称匹配它们。
唯一相关的是 Html助手以模型绑定程序可以理解的方式格式化输入元素名称。
我正在学习 MVC,而且我有 WebForms 背景。
我正在使用默认的 MVC 项目模板,但我不明白文本框如何知道设置模型的 "Email" 属性。
login.cshtml
<div class="form-group">
@Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Email, "", new { @class = "text-danger" })
</div>
</div>
所以我知道 m => m.Email
是一个创建 Func<LoginViewModel, string>
匿名函数(或表达式?)的 lambda 表达式。对我来说,它看起来像一个 getter 函数(用于从数据中呈现 html 文本框值),它接受一个视图模型和 returns 一个字符串,通过访问它是 "Email" 属性.
然而服务器以某种方式知道 "m.Email" 变量的所有信息。它知道所有属性,并且知道在将其发布到服务器时使用文本框中的值对其进行设置。
我的问题是它怎么知道的?服务器如何提取有关 "Email" modelview 变量的信息,你能给我一个例子,说明我如何在给定类似 Func<LoginViewModel, string>
类型的情况下手动执行此操作吗?
恭喜您投身于 Mvc。
lambda 函数仅用于创建文本框 html 字符串,它与它返回无关,它使用它来扫描 属性 的数据注释以进行验证,显示表单等等等等
将数据重新用于您的操作?这取决于模型活页夹。
对控制器的任何 post 操作都将由模型绑定器检查其参数,然后将针对所有参数尝试表单集合键以尝试按名称匹配它们。
所以如果你有这样的行为
public ActionResult SendMeData(string firstName)
将扫描表单集合以查找匹配名字(不区分大小写)的键,如果匹配,它将为其设置参数。
在这个动作签名的情况下
public ActionResult SendMeData(Dude dude)
public class Dude {
public string FirstName {get;set;}
}
它将检查 Dude 是否具有无参数构造函数,如果有,它将创建该对象的新实例,然后扫描其属性以在表单集合中查找匹配的名称并进行适当设置。
因此,您想要在 post 操作中发送回控制器的任何值,只需创建一个名称与 属性 或您想要的参数相匹配的 input/select/textarea,然后所有的魔法都为你处理。
这里发生了很多事情。其中一些是由幕后的 Razor 渲染引擎 "hidden" 提供的。例如,当您在页面顶部指定 @model Foo
时,这实际上是为使用 Foo 作为模型类型的页面创建 class 的语法快捷方式。在 WebForms 中,它看起来像这样:
<% @Page Inherits="System.Web.Mvc.ViewPage<Foo>" %>
不过,Razor 向您隐藏了这一点。实际上,当您使用 @model Foo
ViewPage<Foo>
现在,如果您查看文档中的 ViewPage:
https://msdn.microsoft.com/en-us/library/dd470798(v=vs.118).aspx
你会看到很多有趣的东西。其中就有Html属性.
这是 HtmlHelper<TModel>
类型,如果您的模型是 Foo,则 TModel 是 Foo。
因此,当您(在 Razor 中)编写 @Html.Whatever()
这实际上是一个 HtmlHeler<Foo>.Whatever()
。
https://msdn.microsoft.com/en-us/library/dd492619(v=vs.118).aspx
现在,让我们看看您关心的实际方法。 Html.TextBoxFor()
如果你看上面的linkHtmlHelper,你可以看到上面有很多扩展方法,这些扩展方法是HtmlHelpers的基础MVC 提供。其中有:
https://msdn.microsoft.com/en-us/library/ee703644(v=vs.118).aspx
public static MvcHtmlString TextBoxFor<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression
)
到这里,我们可以看出这是一个扩展方法。它采用TModel 和TProperty 通用参数,并且在函数参数中是this HtmlHelper<TModel> htmlHelper
作为第一个参数。 C# 在扩展方法中对您隐藏了它,但在您调用它时将其传递给方法 @Html.TextBoxFor()
。
请注意,下一个参数是表达式,类型为 Expression<Func<TModel, TProperty>>
,因此,这就是表达式(或 lambda)最终知道模型是什么,并知道 return 的方式属性 类型。它归结为在页面顶部指定模型类型,并使这个气泡向下穿过对象图。
我知道这需要吸收很多东西,但是如果您跟踪对象链,您应该了解它是如何工作的。
至于回传到服务器,这跟这没什么关系。这是模型绑定系统的一部分,它只查看发布到服务器的值和操作方法采用的参数类型,然后尝试根据它们的名称匹配它们。
唯一相关的是 Html助手以模型绑定程序可以理解的方式格式化输入元素名称。