我正在通过电子邮件和密码创建一个简单的登录页面。我有一个类LoginViewModel,它将一个User类作为其中的成员变量。该类包含emailAddress。密码位于主LoginViewModel中。我的用户类引用如下:
public User User { get; set; }
当用户填写电子邮件地址和密码并点击提交时,LoginViewModel会从视图中将字段正确绑定到User类中的电子邮件地址:
@Html.TextBoxFor(m => m.User.Email) // m is the LoginViewModel model
我想知道为什么它不起作用如果我上面的代码看起来像这样:
public User User = new User();
它将User实例中的电子邮件显示为空值。我知道构造函数的使用可能比两者都好,但这两者之间有什么区别。
编辑#1: 在“登录”操作方法上发布时,会找到我为模型中的电子邮件字段输入的值:
public User User { get; set; }
这个不是:
public User User = new User(); // --> because of this email field value shows up null
答案 0 :(得分:1)
这是DefaultModelBinder
的一项功能,它只会将属性绑定到公共getter / setter。如果您浏览源代码,该过程包括初始化模型的新实例,然后尝试设置其属性的值。这里的关键部分是
protected virtual void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
{
...
if (!propertyDescriptor.IsReadOnly && !isNullValueOnNonNullableType)
{
...
propertyDescriptor.SetValue(bindingContext.Model, value) // this is where the value is set
...
}
...
}
当您使用public User User = new User();
时,您只创建一个字段,其IsReadOnly
的{{1}}属性将返回PropertyDescriptor
,因此false
块中的代码为从未执行过,if
的值为User.Email
(null
的默认值)
答案 1 :(得分:-2)
I want to know why it doesn't work if I had the code above looked like this instead:
public User User = new User();
因为基础结构会查找set
方法。它需要是公共制定者的财产。
@Stephen提供的代码的和平并没有描述问题的核心。
这是试图绑定模型属性的DefaultModelBinder
方法。
private void BindProperties(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
IEnumerable<PropertyDescriptor> properties = GetFilteredModelProperties(controllerContext, bindingContext);
foreach (PropertyDescriptor property in properties)
{
BindProperty(controllerContext, bindingContext, property);
}
}
在这里,我们看到GetFilteredModelProperties
尝试通过方法调用PropertyDescriptor
来获取TypeDescriptor.GetProperties
哪个方法调用链最终会返回类型属性而不是字段。