Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default Model Binder does not bind for Nullable types in IEnumerable

I have a controller action whose definition looks like-

public ActionResult ChangeModel( IEnumerable<MyModel> info, long? destinationId)

And the model:

public class MyModel
{
    public string Name; //Gets populated by default binder
    public long? SourceId; //remains null though the value is set when invoked
}

The 'Name' property gets populated in the controller action however the SourceId property remains null. The destinationId which is a long? parameter gets populated as well.

While stepping through the MVC (version 2) source code this is the exception thrown by DefaultModelBinder.

The parameter conversion from type 'System.Int32' to type 'System.Nullable`1[[System.Int64, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]' failed because no type converter can convert between these types.

If the model is changed to long instead of long?, the default model binder sets the value.

public class MyModel
{
    public string Name {get;set;}; //Gets populated by default binder
    public long SourceId {get;set;}; //No longer long?, so value gets set
}

Is this a known issue? Since the MVC source code is optimized, I am not able to step through most of the code.

Update: The request being sent is a Http POST using Json with the source JSon resembling -

{"info":[{"Name":"CL1","SourceId":2}], "destinationId":"1"}
like image 202
QED Avatar asked May 02 '11 13:05

QED


People also ask

Which of the following are relevant to model binding in Web API?

Model Binding is the most powerful mechanism in Web API 2. It enables the response to receive data as per requester choice. i.e. it may be from the URL either form of Query String or Route data OR even from Request Body. It's just the requester has to decorate the action method with [FromUri] and [FromBody] as desired.

What is model binding in C#?

Model binding is a simplistic way to correlate C# code with an HTTP request. The model binding applies to transforming the HTTP request data in the query's form string and form collection of the action method parameters. We can consider these parameters to be primitive type or complex type.

How does model binding work in asp net core application?

Model binding allows controller actions to work directly with model types (passed in as method arguments), rather than HTTP requests. Mapping between incoming request data and application models is handled by model binders.


2 Answers

Maybe it's too late, but I have found a workaround. You can convert the SourceId field to string before sending data. So your JSON data will look like

{"info":[{"Name":"CL1","SourceId":"2"}], "destinationId":"1"}

This worked in my situation (Int32 -> decimal?, ASP NET MVC 3)

like image 116
akakey Avatar answered Sep 28 '22 09:09

akakey


I would recommend you to use properties instead of fields on your view model:

public class MyModel
{
    public string Name { get; set; }
    public long? SourceId { get; set; }
}

Now the following request:

/somecontroller/changemodel?destinationId=123&info[0].Name=name1&info[0].SourceId=1&info[1].Name=name2&info[1].SourceId=2

Populates the model fine.

like image 42
Darin Dimitrov Avatar answered Sep 28 '22 10:09

Darin Dimitrov