2012-12-08 23 views
10

Sto provando a pubblicare un array JSON su un controller MVC. Ma qualunque cosa provi, tutto è 0 o null.Post array JSON al controller mvc

Ho questa tabella che contiene caselle di testo. Ho bisogno di tutte quelle caselle di testo è ID e valore come un oggetto.

Questo è il mio 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; 
    }); 
}); 

Questo è il mio codice della vista:

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

Questo è il controller im cercando di ricevere i dati per:

[HttpPost] 
public ActionResult Update(CustomTypeModel ctm) 
{ 


    return RedirectToAction("Index"); 
} 

Cosa am Sto sbagliando?

+1

Mostra come è il tuo 'CustomTypeModel'. –

+0

quale versione di mvc stai usando? –

+0

Sembra che manchino gli attributi 'name' con il nome delle proprietà che si sta provando a POST. E puoi pubblicare i dati reali che stai postando? La richiesta POST effettiva? – rae1

risposta

50

Ci sono molti problemi con il tuo codice. Iniziamo con il markup. Hai una tabella e all'interno di ogni riga di questa tabella stai includendo i campi nascosti. Tranne che hai hardcoded l'attributo id di quegli elementi nascosti, il che significa che potresti potenzialmente finire con più elementi con lo stesso id nel tuo markup che si traduce in un markup non valido.

Quindi partiamo fissando il vostro codice prima:

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

Bene, ora avete markup valido. Passiamo ora all'evento javascript che verrà attivato quando si fa clic sul pulsante submitTest. Se questo è il pulsante di invio del modulo, ti consigliamo di iscriverti all'evento .submit del modulo anziché dell'evento .click del pulsante di invio. Il motivo è perché un modulo può essere inviato, ad esempio, se l'utente preme il tasto Invio mentre lo stato attivo si trova all'interno di un campo di input. In questo caso l'evento click non verrà attivato.

Quindi:

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

     return false; 
    }); 
}); 

Va bene, viene dopo la parte in cui è necessario raccogliere i valori degli elementi nascosti che sono all'interno della tabella e metterle in un oggetto JavaScript che sarà successivamente JSON serializzare e inviare come parte della richiesta AJAX al server.

andiamo avanti:

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

Finora abbiamo riempito i nostri parametri, cerchiamo di inviarli al server di ora:

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

Ora passiamo al lato server.Come sempre partiamo dalla definizione di un modello di vista:

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

ed un'azione di controllo che avrà una collezione di questo modello:

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

Ed ecco il codice lato client finale:

$(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; 
    }); 
}); 

Ovviamente se il tuo modello di vista è diverso (non lo hai mostrato nella tua domanda) potrebbe essere necessario adattare il codice in modo che corrisponda alla tua struttura, altrimenti il ​​modello predefinito non sarà in grado di per deserializzare il JSON indietro.

+0

sto testando il tuo codice adesso. – Yustme

+4

Una delle migliori risposte che ho visto.Non a causa della complessità ma della capacità di accompagnare la persona attraverso la risposta e mostrare loro come fare qualcosa correttamente. –

-1

Penso che tu faccia le cose in un modo un po 'sbagliato per il mondo MVC. Se hai un modello adatto per legare i tuoi dati con - è meglio usare gli helper che escono dalla scatola invece di usare JavaScript "fatto a mano". Dai un'occhiata a HtmlHelper o AjaxHelper se hai bisogno di chiamate asincrone.

E associare i dati al modello utilizzando la notazione @Html.TextBoxFor() all'interno del blocco @Html.BeginForm Ciò semplifica notevolmente il codice e riduce la quantità di javascript, che è molto meglio per la manutenzione.

Nella parte server è necessario implementare il modello personalizzato e modificare le impostazioni per fare richiesta di handle per l'azione del controller corrente tramite il modello di raccoglitore. Ti porterà a scrivere un codice serveride, ma il codice staticamente digitato sembra più semplice da codificare e testare o da me, ed è meglio adattarlo alle tue esigenze, perché preferisco che JavaScript faccia cose che dovrebbe fare => gestire l'interfaccia utente, ma non costruire il modello per l'analisi corretta sul lato server. È meglio adattarsi al principio della responsabilità unica.

Vai a questa video, questo è semplice tutorial come fare

+0

è un tipo complesso. Non posso essere legato così, almeno non ho ancora capito come. Il javascript funziona per me ora. Ma per la cronaca, non esiste @ Html.InputFor() – Yustme

+0

Thx su InputFor, ho codificato java l'ultima volta ed è difficile ricordare correttamente tutti i nomi. Modifico la mia risposta, potresti dare un'occhiata a questo. – Ph0en1x

+0

Beh, sembra fantastico, ma ho già provato un sacco di cose per evitare javascript. È un modello complesso. Inoltre, ho usato @ Html.TextBoxFor(), ma non so come ottenerne i dati usando javascript. – Yustme

6

c'è un altro modo più semplice: utilizzando Query String per inviare i tuoi dati. Se ti sei intruso, l'approccio corrente è errato perché il tipo di dati dell'array JSON è string non CustomTypeModel.

Prima di tutto, rimuovere l'opzione data ajax. Non ne abbiamo più bisogno.

In secondo luogo, cambiare il controller simile al seguente:

[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"); 
} 

Nota 1: E 'importante che i nomi dei vostri CustomTypeModel proprietà essere lo stesso di quello che si entra come gli elementi JSON. Così, il vostro CustomTypeModel dovrebbe essere simile a questo:

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

Nota 2: Questo metodo è utile quando si desidera inviare i dati tramite stringhe di query. Quindi, il tuo url può essere così:

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

ha funzionato per me. Grazie –

Problemi correlati