Is there a reason why the default modelbinder doesn't bind to fields?
Asked Answered
M

3

6

I'm using ASP.NET MVC3 and i'm wondering that the default modelbinder binds to public properties but not to public fields.

Normally i just define the model classes with properties but sometimes i use some predefined classes which contains some fields. And everytime i have to debug and remember that the modelbinder just don't like fields.

The question: Whats the reason behind it?

Moneybag answered 19/12, 2011 at 9:6 Comment(0)
S
2

but sometimes i use some predefined classes which contains some fields

While I cannot answer your question about the exact reason why the default model binder works only with properties (my guess is that it respects better encapsulation this way and avoids modifying internal state of the object which is what fields represent) I can say that what you call predefined classes should normally be view models. You should always use view models to and from your controller actions. Those view models are classes that are specifically defined to meet the requirements of the given view.

So back to the main point: fields are supposed to be modified only from within the given class. They should not be accessed directly from the outside. They represent and hold internal state of the class. Properties on the other hand is what should be exposed to the outside world. Imagine that in the property getter/setter you had some custom logic. By modifying directly the field this custom logic would be broken and potentially bring the object into an inconsistent state.

Sled answered 19/12, 2011 at 9:44 Comment(4)
Ok, but for that you have the access modifiers. If i don't want a field to be set directly, i just declare it private. Viewmodel classes are normally just datacontainers and mostly don't contain much logic - so i thought it could be ok to just use public fields.Moneybag
@Jan, normally fields should be private.Sled
@gdoron, I have to disagree with the fact that you should not have logic in the properties getters. I would say: in most cases you don't put logic there but there is nothing wrong with putting if your scenario requires one.Sled
Logic in ViewModel properties?! can't think of a good reason for that. Please be kind and share scenario where it's needed. And if Real Entity is used instead of a ViewModel, So that is (one of)the problem(a)...Isopropanol
I
0

Maybe the reason for ignoring fields is to increase performance of the binder. Instead of searching all the Fields and properties. The Model Binder search for Properties only.

Though I think the Model Binder use cache to improve performance.

Isopropanol answered 19/12, 2011 at 9:38 Comment(0)
K
0

DefaultModelBinder exposes a public method: DefaultModelBinder.BindModel, and a number of protected method available for overriding. All of them listed here.

Besides the model, these method refer to properties only, not fields, like

  • GetModelProperties,
  • GetFilteredModelProperties,
  • GetPropertyValue,
  • OnXYZValidating,
  • OnXYZValidated,
  • OnXYZUpdating,
  • OnXYZUpdated,
  • GetXYZValue,

where XYZ stands for either Model, or Property/ies, or both, and so on.

As you can see there is no Fields mentioned with these names whatsoever. As Darin explained no direct changes to Model's state are tolerated by the Binder. Hence no Field in its methods.

And also, you may wish to take a look at another important class: ModelBindingContext. An instance of this class gets passed to the BindModel, and subsequently to BindSimpleModel, and BindComplexModel, depending on model type (string, int,... are considered simple, everything else is complex).

So, this context has the following properties:

  • ModelXYZ, and
  • PropertyXYZ.

In other words you have no means to reference the fields in your ViewModel unless you do not override these classes and undertake special actions to do so.

But again, beware of fighting the framework, its always easier to follow it instead.

EDIT: The ModelMetadata class holds all the data needed to bind the model. Its code however, shows no sign of fields, field names, etc. Only properties are referenced and accessed. So, even if you try to inherit and override DefaultModelBinder and ModelBinderContext, you still won't be able to access fiellds, nevermind what their access modifier is: public, private, etc.

Hope this explains most of it.

Kentkenta answered 8/9, 2015 at 8:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.