ASP.NET MVC Post list goes null in very strange circumstances

So, I have such a controller:

public class TestController : Controller { // // GET: /Test/ public ActionResult Index() { return View("Test"); } public ActionResult Post(IList<Test> LanguageStrings, IList<Test> LanguageStringsGroup, IList<string> Deleted, IList<string> DeletedGroup) { if (LanguageStrings == null) { throw new ApplicationException("NULL"); } return View("Test"); } } public class Test { public string Val { get; set; } public string Another { get; set; } } 

And here is a view:

 <h2>Test</h2> @using (Html.BeginForm("Post", "Test")) { @Html.Hidden("LanguageStrings[0].Val", "test1") @Html.Hidden("LanguageStrings[0].Another") @Html.Hidden("LanguageStrings[1].Val", "test2") @Html.Hidden("LanguageStrings[1].Another") @Html.Hidden("LanguageStringsGroup[0].Val", "test4") @Html.Hidden("Deleted[0]") @Html.Hidden("Deleted[1]") @Html.Hidden("Deleted[2]") @Html.Hidden("DeletedGroup[0]") <button>Post</button> } 

When I submit the form, my controller throws an exception because LanguageStrings is null. The strange part that I mentioned in the title is that if I add another entry to the list, everything will work. Like this:

 <h2>Test</h2> @using (Html.BeginForm("Post", "Test")) { @Html.Hidden("LanguageStrings[0].Val", "test1") @Html.Hidden("LanguageStrings[0].Another") @Html.Hidden("LanguageStrings[1].Val", "test2") @Html.Hidden("LanguageStrings[1].Another") @Html.Hidden("LanguageStrings[2].Val", "test3") @Html.Hidden("LanguageStrings[2].Another") @Html.Hidden("LanguageStringsGroup[0].Val", "test4") @Html.Hidden("Deleted[0]") @Html.Hidden("Deleted[1]") @Html.Hidden("Deleted[2]") @Html.Hidden("DeletedGroup[0]") <button>Post</button> } 

It also works when I delete the Deleted Items list. Like this:

 <h2>Test</h2> @using (Html.BeginForm("Post", "Test")) { @Html.Hidden("LanguageStrings[0].Val", "test1") @Html.Hidden("LanguageStrings[0].Another") @Html.Hidden("LanguageStrings[1].Val", "test2") @Html.Hidden("LanguageStrings[1].Another") @Html.Hidden("LanguageStringsGroup[0].Val", "test4") @Html.Hidden("DeletedGroup[0]") <button>Post</button> } 

This has something to do with the name I use. I already solved the problem of renaming LanguageStrings to something else. But I would like to understand what is happening here, because, probably, I could learn something from him, how MVC cards request the body and can avoid such labor-intensive problems. Please help me and explain the reason for this.

+6
source share
2 answers

You found a bug in PrefixContainer MVC 4, which is already fixed in MVC 5.

Here is the corrected version with error comments:

 internal bool ContainsPrefix(string prefix) { if (prefix == null) { throw new ArgumentNullException("prefix"); } if (prefix.Length == 0) { return _sortedValues.Length > 0; // only match empty string when we have some value } PrefixComparer prefixComparer = new PrefixComparer(prefix); bool containsPrefix = Array.BinarySearch(_sortedValues, prefix, prefixComparer) > -1; if (!containsPrefix) { // If there something in the search boundary that starts with the same name // as the collection prefix that we're trying to find, the binary search would actually fail. // For example, let say we have foo.a, foo.bE and foo.b[0]. Calling Array.BinarySearch // will fail to find foo.b because it will land on foo.bE, then look at foo.a and finally // failing to find the prefix which is actually present in the container (foo.b[0]). // Here we're doing another pass looking specifically for collection prefix. containsPrefix = Array.BinarySearch(_sortedValues, prefix + "[", prefixComparer) > -1; } return containsPrefix; } 
+5
source

I had a lot more success with @ Html.HiddenFor () to send back to the controller. The code will look something like this:

 @for (int i = 0; i < @Model.LanguageStrings.Count; i++) { @Html.HiddenFor(model => model.LanguageStrings[i].Val, string.Format("test{0}", i)) @Html.HiddenFor(model => model.LanguageStrings[i].Another) } 

Most HTML helper methods have a "For" helper that is designed to bind data to models. Here's another post on the site that explains the For methods well: What is the difference between Html.Hidden and Html.HiddenFor

0
source

Source: https://habr.com/ru/post/958561/


All Articles