之间的区别

时间:2014-11-22 15:30:06

标签: c# asp.net-mvc model-binding

我正在通过电子邮件和密码创建一个简单的登录页面。我有一个类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

2 个答案:

答案 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.Emailnull的默认值)

答案 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哪个方法调用链最终会返回类型属性而不是字段。