0

So if you post empty string to a controller like this

<input type="text" value="" name="idList">

and try to bind it to a List very strange stuff occurs

enter image description here

Does anybody faced this issue?

Why it adds default int value to a list?

1 Answers1

2

No, this is not strange, nor is it unexpected. The problem here is that you don't understand the difference between a reference type (string) and a value type (int) and what their default values are.

An int cannot be null, and must always have a value. In this case, the model binder is trying to convert a blank string to your list and failing, so it creates a "default" value for the type, which for int is 0 (since it can't be null). The model binder always uses the default value for the type if it fails to convert, which for nullable types is null, but for value types is whatever it's default is.

Simultaneously, you should have an Error placed in your ModelState.Errors list that informs you about this error. If you want null, then you need a List nullable int.

Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291
  • 1
    Thanks for the response @Erik Funkenbusch. Yes I ofc default(int) == 0 but List is reference type: typeof(int).IsValueType; //true typeof(List).IsValueType; //false Thus I was expecting that empty string will be converted to null or empty List. Moreover if you try to bind empty string to List you will get List with one null item (which is default(int?)) – Grebets Kostyantyn Sep 26 '14 at 16:06
  • @GrebetsKostyantyn - Yes, that's correct.. because you have one empty item you are posting to the client. You don't get a null list, because you have an item... it just has an invalid content. It would only be null if there were no items posted at all. The reason for this should be obvious... you can't have a failed validation if the item doesn't exist in the collection, thus you can't know that the item failed. – Erik Funkenbusch Sep 26 '14 at 16:21
  • @GrebetsKostyantyn - look, stop asking "why" and start accepting that it just works this way. You will get an item in your collection if there is a posted item, regardless of whether it passes validation or not. If the item cannot be parsed by the type, it will have a default value. If it can be represented by the type, but fails validation (for instance, not in range, or fails a regex) then it will still contain the value submitted I believe. It only contains a default if the value cannot be represented by the type. – Erik Funkenbusch Sep 26 '14 at 16:28
  • @GrebetsKostyantyn - Also, remember, you're submitting an *ITEM* in the list, not the list itself. That's why the *ITEM* is defaulted. The list itself is created by the binder, because the binder sees that you are expecting a list in your parameters. If it sees an item of the name of your parameter, it looks at the type and instantiates it. If it sees that this is a collection, it adds the item to that collection, if validation fails it adds a default value. The list itself is entirely a server-side concept. – Erik Funkenbusch Sep 26 '14 at 16:33
  • Empty string can't be converted to some int value thus - fallback to default(int) and we get 0 as first item. Thank you @Erik Funkenbusch – Grebets Kostyantyn Sep 26 '14 at 16:44