2012-12-08 19 views
10

Próbuję wysłać tablicę JSON do kontrolera MVC. Ale bez względu na to, co próbuję, wszystko ma wartość 0 lub zero.Post JSON array do kontrolera mvc

Mam tę tabelę, która zawiera pola tekstowe. Potrzebuję ze wszystkich tych pól tekstowych, że to ID i wartość jako obiekt.

To mój Javascript:

$(document).ready(function() { 

    $('#submitTest').click(function (e) { 

     var $form = $('form'); 
     var trans = new Array(); 

     var parameters = { 
      TransIDs: $("#TransID").val(), 
      ItemIDs: $("#ItemID").val(), 
      TypeIDs: $("#TypeID").val(), 
     }; 
     trans.push(parameters); 


     if ($form.valid()) { 
      $.ajax(
       { 
        url: $form.attr('action'), 
        type: $form.attr('method'), 
        data: JSON.stringify(parameters), 
        dataType: "json", 
        contentType: "application/json; charset=utf-8", 
        success: function (result) { 
         $('#result').text(result.redirectTo) 
         if (result.Success == true) { 
          return fase; 
         } 
         else { 
          $('#Error').html(result.Html); 
         } 
        }, 
        error: function (request) { alert(request.statusText) } 
       }); 
     } 
     e.preventDefault(); 
     return false; 
    }); 
}); 

To jest mój kod Widok:

<table> 
     <tr> 
      <th>trans</th> 
      <th>Item</th> 
      <th>Type</th> 
     </tr> 

     @foreach (var t in Model.Types.ToList()) 
     { 
      { 
      <tr> 
       <td>     
        <input type="hidden" value="@t.TransID" id="TransID" /> 
        <input type="hidden" value="@t.ItemID" id="ItemID" /> 
        <input type="hidden" value="@t.TypeID" id="TypeID" /> 
       </td> 
      </tr> 
      } 
     } 
</table> 

ten kontroler im próbuje odbierać dane:

[HttpPost] 
public ActionResult Update(CustomTypeModel ctm) 
{ 


    return RedirectToAction("Index"); 
} 

co ja Robię źle?

+1

Pokaż, jak wygląda Twój 'CustomTypeModel'. –

+0

której wersji mvc używasz? –

+0

Wygląda na to, że może brakować atrybutów 'name' z nazwami właściwości, które próbujesz POST. Czy możesz publikować rzeczywiste dane, które publikujesz? Rzeczywiste żądanie POST? – rae1

Odpowiedz

50

Istnieje wiele problemów z kodem. Zacznijmy od znaczników. Masz stół, a wewnątrz każdego wiersza tej tabeli znajdują się ukryte pola. Poza tym, że na stałe utknąłeś w atrybucie tych ukrytych elementów, co oznacza, że ​​możesz potencjalnie skończyć z wieloma elementami o tym samym id w swoim znaczniku, co skutkuje nieprawidłowym znacznikiem.

Więc zacznijmy ustalając najpierw znaczników:

@foreach (var t in Model.Types.ToList()) 
{ 
    <tr> 
     <td>     
      <input type="hidden" value="@t.TransID" name="TransID" /> 
      <input type="hidden" value="@t.ItemID" name="ItemID" /> 
      <input type="hidden" value="@t.TypeID" name="TypeID" /> 
     </td> 
    </tr> 
} 

Dobra, teraz masz prawidłowych znaczników. Przejdźmy teraz do zdarzenia javascript, które zostanie uruchomione po kliknięciu przycisku submitTest. Jeśli jest to przycisk przesyłania formularza, zalecamy zasubskrybowanie zdarzenia .submit formularza zamiast zdarzenia .click jego przycisku przesyłania. Powodem tego jest to, że formularz może zostać przesłany, na przykład, jeśli użytkownik naciśnie klawisz Enter, gdy fokus znajduje się wewnątrz jakiegoś pola wejściowego. W takim przypadku zdarzenie kliknięcia nie zostanie wyzwolone.

Więc:

$(document).ready(function() { 
    $('form').submit(function() { 
     // code to follow 

     return false; 
    }); 
}); 

Dobra, następny przychodzi część, gdzie trzeba zebrać wartości ukrytych elementów, które są w środku tabeli i umieścić je w JavaScript Object że będziemy następnie JSON serialize i wysłać jako część żądania AJAX do serwera.

Chodźmy naprzód:

var parameters = []; 
// TODO: maybe you want to assign an unique id to your table element 
$('table tr').each(function() { 
    var td = $('td', this); 
    parameters.push({ 
     transId: $('input[name="TransID"]', td).val(), 
     itemId: $('input[name="ItemID"]', td).val(), 
     typeId: $('input[name="TypeID"]', td).val() 
    }); 
}); 

Jak dotąd wypełnione nasze parametry, niech wysłać je do serwera teraz:

$.ajax({ 
    url: this.action, 
    type: this.method, 
    data: JSON.stringify(parameters), 
    contentType: 'application/json; charset=utf-8', 
    success: function (result) { 
     // ... 
    }, 
    error: function (request) { 
     // ... 
    } 
}); 

Teraz przejdźmy do strony serwera.Jak zawsze zaczynamy od zdefiniowania widoku modelu:

public class MyViewModel 
{ 
    public string TransID { get; set; } 
    public string ItemID { get; set; } 
    public string TypeID { get; set; } 
} 

i działania kontrolera, która będzie miała kolekcję tego modelu

[HttpPost] 
public ActionResult Update(IList<MyViewModel> model) 
{ 
    ... 
} 

A oto ostateczny kod po stronie klienta:

$(function() { 
    $('form').submit(function() { 
     if ($(this).valid()) { 
      var parameters = []; 
      // TODO: maybe you want to assign an unique id to your table element 
      $('table tr').each(function() { 
       var td = $('td', this); 
       parameters.push({ 
        transId: $('input[name="TransID"]', td).val(), 
        itemId: $('input[name="ItemID"]', td).val(), 
        typeId: $('input[name="TypeID"]', td).val() 
       }); 
      }); 

      $.ajax({ 
       url: this.action, 
       type: this.method, 
       data: JSON.stringify(parameters), 
       contentType: 'application/json; charset=utf-8', 
       success: function (result) { 
        // ... 
       }, 
       error: function (request) { 
        // ... 
       } 
      }); 
     } 
     return false; 
    }); 
}); 

Oczywiście, jeśli twój model widoku jest inny (nie pokazałeś go w pytaniu), może być konieczne dostosowanie kodu tak, aby pasował do twojej struktury, w przeciwnym razie domyślny segregator modelu nie będzie w stanie ponownie deserializować JSON.

+0

testuję teraz twój kod. – Yustme

+4

Jedna z najlepszych odpowiedzi, jakie widziałem.Nie ze względu na złożoność, ale zdolność do przejścia osoby przez odpowiedź i pokazania, jak zrobić coś poprawnie. –

-1

Myślę, że robisz coś w zły sposób dla świata MVC. Jeśli masz odpowiedni model do wiązania danych za pomocą - lepiej korzystaj z pomocy wychodzących z pudełka, zamiast używać "ręcznie" JavaScript. Zajrzyj do HtmlHelper lub AjaxHelper, jeśli potrzebujesz połączeń asynchronicznych.

I wiążę dane z modelem przy użyciu @Html.TextBoxFor() notacji wewnątrz bloku @Html.BeginForm To znacznie uprości kod i zredukuje ilość javascriptu, co jest znacznie lepsze w przypadku konserwacji.

W części serwerowej należy zaimplementować niestandardowy segregator modelu i zmienić ustawienia, aby żądanie obsługi bieżącego działania kontrolera było realizowane za pomocą segregatora. Zajmie Ci to napisanie kodu serwery, ale statycznie wpisany kod wygląda na łatwiejszy do zakodowania i przetestowania, i to jest lepszy garnitur lub potrzeby twojej aplikacji, ponieważ wolę JavaScript robiąc rzeczy, które powinien zrobić => zarządzając interfejsem, ale nie budując modelu do poprawnego analizowania na serwerze. Jest to lepsze rozwiązanie dla zasady jednej odpowiedzialności.

zobaczyć ten video, jest to prosty poradnik jak to zrobić

+0

to typ złożony. Nie można się tak związać, przynajmniej nie wiedziałem, jak jeszcze. Javascript działa teraz dla mnie. Ale dla rekordu, nie ma @ Html.InputFor() – Yustme

+0

Thx about InputFor, I kodowania java ostatnim razem i trudno jest zapamiętać wszystkie nazwy poprawnie. Edytuję odpowiedź, możesz na nią spojrzeć. – Ph0en1x

+0

Cóż, brzmi świetnie, ale już próbowałem wielu rzeczy, aby uniknąć javascript. To skomplikowany model. Również użyłem @ Html.TextBoxFor(), ale nie wiem, jak uzyskać dane z niego za pomocą javascript. – Yustme

6

Jest inny prostszy sposób: za pomocą Query String wysłać swoje dane. Jeśli jesteś zainteresowany, Twoje obecne podejście jest błędne, ponieważ typ danych tablicy JSON to string, a nie CustomTypeModel.

Po pierwsze, usuń opcję ajax w wersji data. Już tego nie potrzebujemy.

drugie, zmienić kontroler jak poniżej:

[HttpPost] 
public ActionResult Update(string json) 
{ 
    // this line convert the json to a list of your type, exactly what you want. 
    IList<CustomTypeModel> ctm = 
     new JavaScriptSerializer().Deserialize<IList<CustomTypeModel>>(json); 

    return RedirectToAction("Index"); 
} 

UWAGA1: To ważne, że nazwy właściwościach CustomTypeModel być takie samo jak to, co wpisać jako elementy JSON. Tak, twój CustomTypeModel powinno być tak:

public class CustomTypeModel 
{ 
    // int, or maybe string ... whatever you want. 
    public int TransIDs { get; set; } 
    public int ItemIDs { get; set; } 
    public int TypeIDs { get; set; } 
} 

Uwaga2: Takie podejście jest użyteczne, gdy chcesz wysłać dane przez ciągów zapytań. Twój adres URL może wyglądać następująco:

url: '/controller/action?json=' + JSON.stringify(trans) 
+1

pracował dla mnie. dzięki –

Powiązane problemy