ASP.NET MVC 4 - ModelBinder Error

So, I played with my ASP.NET MVC 4 solution. Everything worked fine, adding things, but something weird started.

One of the properties of my models was null, although I had elements in Json passed to it.

It was a javascript / json object that passed it:

var obj = { "plc": "False", "al": ["386", "710"], "pl": ["9530", "211", "783"] }; 

I used the Custom Model binding ... thought it might be a problem, so I disabled it.

Tried using JavaScriptSerializer from .NET to see how it works:

 var reader = new StreamReader(Request.InputStream); Request.InputStream.Position = 0; var readToEnd = reader.ReadToEnd(); var javaScript = new JavaScriptSerializer(); var searchFarmOptions = javaScript.Deserialize<Test>(readToEnd); 

Got all the properties set ... WOOT.

So, I tried a clean ASP.NET MVC 4 solution. To reproduce the error.

This is from the view of Index.cshtml

 @{ ViewBag.Title = "title"; } <h1>Title</h1> Testing ... <script src="/Scripts/jquery-1.8.2.min.js" type="text/javascript"></script> <script> $(function() { var obj = { "1pllort": "False", "1plc": "true", "al": ["386", "710"], "pl": ["9530", "211", "783"] }; var options = { "contentType": "application/json; charset=UTF-8", "type": "POST", "data" : JSON.stringify(obj) }; $.ajax("/Home/TestPost", options).done(function(data) { console.log(data); }); }); </script> 

This is my HomeController

 using System.Collections.Generic; using System.Web.Mvc; namespace MvcApplication3.Controllers { public class HomeController : Controller { public ActionResult Index() { return View("Index"); } [HttpPost] public ActionResult TestPost(Test model) { return Json(model); } } public class Test { public List<int> PL { get; set; } public List<int> AL { get; set; } public bool PLC { get; set; } public bool ALC { get; set; } } } 

Yes, the error still exists.

Whenever I have a property starting with "pl" as the name of my list, the list "pl" is null.

Alternatively, it can be any name starting with "pl" ... like "plchecked"

If I rename "plc" to "cpl" its work.

So what is going on here ... are there any restrictions on naming in the connecting device? What am I missing here?

Update 1

Job

Now on the server side of PL there are correct values, etc., but not a zero, but a list of numbers.

 var obj = { "pl": ["9530", "211", "783"], "1plc": "false", "pl-some-odd-value": "false", "al": ["386", "710"], "alc": "false" }; 

Does not work

Now on the server side of PL there is a null value.

 var obj = { "pl": ["9530", "211", "783"], "al": ["386", "710"], "alc": "false", "pl-odd-value": "false" }; 

Job

PL has 3 values ​​som string json object ...

 var obj = { "pl": ["9530", "211", "783"], "al": ["386", "710"], "alc": "false", "odd-value-pl": "false" }; 
+4
source share
3 answers

Install the ImranB.ModelBindingFix nuget package . I think you are getting into the error that I mentioned in this blog post .

+5
source

There is definitely a mistake. I just spent a few hours debugging the MVC 4 source code for the same problem. The main root makes it have a collection whose name is the beginning of another property name. In your example: pl and pl-odd-value.

If you play a little more, you may find that sometimes it works correctly. The reason this seems random is because the model binder performs a binary search to find the value for the binding. Binary search uses the divide and conquer approach to find a property in a sorted list of properties that have been published. If the search verifies the p1 odd value in its division and conquest, a problem arises. If the search skips this value, no problem.

This problem is most common when you simply have a pl collection with 1 element and the pl-odd-value property in the object.

Here is some more information related to this. There is a sorted list of all values ​​sent back. If the test fails, the sorted list looks like this:

 alc, "false", al[0], "386" al[1], "710" pl-odd-value, "false" pl[0], "9530" pl[1], "211" pl[2], "783" 

Note that the sort order uses StringComparer.OrdinalIgnoreCase, which places the square brackets AFTER the text element. When the MVC does its binary search for the al or pl collection, it searches for al or pl, NOT al [or pl [. By searching for the collection name without a square bracket, al <alc, no more than alc. The problem is that we want to follow alc or pl-odd-value to get into the collection.

The workaround is to make sure that none of your property names begins with the name of any of your collection property names. Rename your al collection, possibly to al_collection, and your PL collection, possibly to pl_collection.

+3
source

Great answer!

I had the same problem today and spent almost 3 hours trying to figure out what the problem was when I suddenly realized that properties with the same prefix have something strange

More details here:

-1
source

All Articles