2013-11-21 13 views
6

Mam więc kontroler takiego:lista ASP.NET MVC post staje się zerowa w bardzo dziwnych okolicznościach

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; } 
    } 

i widok takiego:

<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> 
} 

Kiedy zakładać postaci mojego kontrolera zgłasza wyjątek, ponieważ LanguageStrings ma wartość null. Dziwną częścią, o której wspomniałem w tytule, jest to, że jeśli dodaję jeszcze jeden rekord do listy, wszystko działa. Jak to:

<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> 
} 

działa również kiedy usunąć listę „usunięte”. Jak to:

<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> 
} 

To ma coś wspólnego z nazewnictwa używam. Rozwiązałem już problem z przemianowaniem LanguageStrings na coś innego. Chciałbym jednak zrozumieć, co się tutaj dzieje, ponieważ prawdopodobnie mógłbym się z niego dowiedzieć, w jaki sposób mapy MVC żądają treści i będą w stanie uniknąć podobnych czasochłonnych problemów. Proszę mi pomóc i wyjaśnić przyczynę tego.

Odpowiedz

5

Znalazłeś błąd w PrefixContainer MVC 4, która została już ustalona w MVC 5.

Oto wersja utrwalono Komentarze na temat błędu:

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's 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's 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; 
} 
+0

gdzie powinien być ten kod? – raklos

+0

MVC5 ma ten kod, więc po prostu uaktualnij do MVC5. Oto najnowszy kod źródłowy PrefixContainer https://aspnetwebstack.codeplex.com/SourceControl/latest#src/Common/PrefixContainer.cs – LostInComputer

0

Miałem o wiele więcej sukcesów dzięki @ Html.HiddenFor() do wysyłania z powrotem do kontrolera. Kod będzie wyglądał tak:

@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) 
} 

Większość HTML metody pomocnicze mają „Dla” pomocnika, który ma być używany do wiązania danych do modeli. Oto kolejny post na stronie, która wyjaśnia „Dla” metody dobrze: What is the difference between Html.Hidden and Html.HiddenFor