Difference between

I am creating a simple email and password login page. I have a LoginViewModel class that will have a User class as a member variable inside it. The class contains the email address. The password is inside the main login LoginViewModel. The My User class reference looks like this:

public User User { get; set; }

      

when the user fills in the email and password and clicks submit, the LoginViewModel correctly binds this field to the email address inside the User class from the view:

@Html.TextBoxFor(m => m.User.Email) // m is the LoginViewModel model

      

I want to know why this would not work if the code above appeared instead:

public User User = new User();

      

It displays the email message inside the user instance as null. I know using the constructor is probably better than both, but what is the difference between the two.

EDIT # 1: When posting to the Login action method, this finds the value I entered for the email field in the model:

public User User { get; set; }

      

this is NOT NOT:

public User User = new User(); // --> because of this email field value shows up null

      

+3


source to share


2 answers


This is a function DefaultModelBinder

that will only bind properties to public getter / setters. If you examine the source code, the process involves initializing a new instance of your model and then trying to set the value of its properties. The key part is here

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
    ...
  }
  ...
}

      



When you are using public User User = new User();

, you create only the field and property of IsReadOnly

his PropertyDescriptor

return false

, so the code in the block if

is never executed, and the value User.Email

is equal to null

(the default value of string

)

+1


source


I want to know why it doesn't work if I had the code above looked like this instead:

public User User = new User();

      

As the framework looks for a method set

. This must be a property with a public setter.

The world of code provided by @Stephen does not describe the essence of the problem. Here is a method DefaultModelBinder

that tries to bind the properties of the model.



private void BindProperties(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
     IEnumerable<PropertyDescriptor> properties = GetFilteredModelProperties(controllerContext, bindingContext);
     foreach (PropertyDescriptor property in properties)
     {
          BindProperty(controllerContext, bindingContext, property);
     }
}

      

Here we see what is GetFilteredModelProperties

trying to get PropertyDescriptor

, which, along the chain of metosis, ends with a call to a method TypeDescriptor.GetProperties

that returns properties of type not field.

-2


source







All Articles