Modo corretto di utilizzare AJAX Post in jquery per passare il modello dalla vista MVC3 fortemente tipizzata


100

Sono un programmatore web alle prime armi quindi per favore perdonami se un po 'del mio "gergo" non è corretto. Ho un progetto che utilizza ASP.NET utilizzando il framework MVC3.

Sto lavorando a una visualizzazione amministratore in cui l'amministratore modificherà un elenco di apparecchiature. Una delle funzioni è un pulsante "aggiorna" che desidero utilizzare jquery per modificare dinamicamente la voce sulla pagina web dopo aver inviato un messaggio al controller MVC.

Presumo che questo approccio sia "sicuro" in un unico ambiente di amministrazione in cui vi è la minima preoccupazione che la pagina web non sia più sincronizzata con il database.

Ho creato una vista fortemente tipizzata e speravo di passare i dati del modello al controllo MVC utilizzando un post AJAX.

Nel seguente post, ho trovato qualcosa di simile a quello che sto cercando di fare: JQuery Ajax e ASP.NET MVC3 che causano parametri nulli

Userò il codice di esempio dal post sopra.

Modello:

public class AddressInfo 
{
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
    public string Country { get; set; }
}

controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Check(AddressInfo addressInfo)
    {
        return Json(new { success = true });
    }
}

script in Visualizza:

<script type="text/javascript">
var ai = {
    Address1: "423 Judy Road",
    Address2: "1001",
    City: "New York",
    State: "NY",
    ZipCode: "10301",
    Country: "USA"
};

$.ajax({
    url: '/home/check',
    type: 'POST',
    data: JSON.stringify(ai),
    contentType: 'application/json; charset=utf-8',
    success: function (data.success) {
        alert(data);
    },
    error: function () {
        alert("error");
    }
});
</script>

Non ho ancora avuto la possibilità di utilizzare quanto sopra. Ma mi chiedevo se questo fosse il metodo "migliore" per restituire i dati del modello al controllo MVC utilizzando AJAX?

Dovrei essere preoccupato per l'esposizione delle informazioni sul modello?

Risposte:


72

Puoi saltare la dichiarazione var e il stringify. Altrimenti, funzionerà bene.

$.ajax({
    url: '/home/check',
    type: 'POST',
    data: {
        Address1: "423 Judy Road",
        Address2: "1001",
        City: "New York",
        State: "NY",
        ZipCode: "10301",
        Country: "USA"
    },
    contentType: 'application/json; charset=utf-8',
    success: function (data) {
        alert(data.success);
    },
    error: function () {
        alert("error");
    }
});

Grazie per aver sottolineato il leggero aggiustamento. C'è qualche preoccupazione con l'esposizione della struttura del modello dal punto di vista della sicurezza?
John Stone

Niente di eclatante si distingue come un problema di sicurezza per me. Se sei davvero preoccupato, puoi sempre creare un raccoglitore di modelli personalizzato sul lato mvc.
Craig M

8
Questo è fallito per me. Ho dovuto utilizzare JSON.stringify ({...}) affinché la chiamata funzionasse in MVC5.
Johncl

Ho notato che devo fare lo stesso quando lavoro con i controller API. Questa risposta è stata scritta 4 anni fa, prima che esistessero i controller API.
Craig M

1
Dio diavolo, avevo dataType invece di contentType, quello mi capisce sempre !!
Phil

175

Ho trovato 3 modi per implementarlo:

Classe C #:

public class AddressInfo {
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
    public string Country { get; set; }
}

Azione:

[HttpPost]
public ActionResult Check(AddressInfo addressInfo)
{
    return Json(new { success = true });
}

JavaScript puoi farlo in tre modi:

1) Stringa di query:

$.ajax({
    url: '/en/Home/Check',
    data: $('#form').serialize(),
    type: 'POST',
});

I dati qui sono una stringa.

"Address1=blah&Address2=blah&City=blah&State=blah&ZipCode=blah&Country=blah"

2) Array di oggetti:

$.ajax({
    url: '/en/Home/Check',
    data: $('#form').serializeArray(),
    type: 'POST',
});

I dati qui sono un array di coppie chiave / valore:

=[{name: 'Address1', value: 'blah'}, {name: 'Address2', value: 'blah'}, {name: 'City', value: 'blah'}, {name: 'State', value: 'blah'}, {name: 'ZipCode', value: 'blah'}, {name: 'Country', value: 'blah'}]

3) JSON:

$.ajax({
      url: '/en/Home/Check',
      data: JSON.stringify({ addressInfo:{//missing brackets
          Address1: $('#address1').val(),
          Address2: $('#address2').val(),
          City: $('#City').val(),
          State: $('#State').val(),
          ZipCode: $('#ZipCode').val()}}),
      type: 'POST',
      contentType: 'application/json; charset=utf-8'
});

I dati qui sono una stringa JSON serializzata. Notare che il nome deve corrispondere al nome del parametro nel server !!

='{"addressInfo":{"Address1":"blah","Address2":"blah","City":"blah","State":"blah", "ZipCode", "blah", "Country", "blah"}}'

1
Ho appena trovato questa risposta fantastica e completa che ha risolto domande che non sapevo di avere ancora. +1, grazie!
SeanKilleen

# 2 era quello che stavo cercando. Questa dovrebbe essere la risposta.
TheGeekZn

EDIT: ho dovuto usare il data: $('input, textarea, select').serialize(),mio per funzionare.
TheGeekZn

Ehi Jazaret !! come passare la data al modello con il 3 ° approccio ??
Guruprasad Rao

1
Ci scusiamo per il ritardo @GuruprasadRao Per passare una data puoi fare in modo che la data e l'ora siano una stringa nel codice javascript e MVC la tradurrà in un oggetto DateTime.
Jazaret

12

Questo è il modo in cui ha funzionato per me:

$.post("/Controller/Action", $("#form").serialize(), function(json) {       
        // handle response
}, "json");

[HttpPost]
public ActionResult TV(MyModel id)
{
    return Json(new { success = true });
}

8

quello che hai va bene, tuttavia per risparmiare un po 'di digitazione, puoi semplicemente usarlo per i tuoi dati

dati: $ ('# formId'). serialize ()

vedere http://www.ryancoughlin.com/2009/05/04/how-to-use-jquery-to-serialize-ajax-forms/ per i dettagli, la sintassi è piuttosto semplice.


Per poter utilizzare la funzione serialize, la mia comprensione è che ogni membro della classe deve essere utilizzato in un oggetto form. Se è corretto, potrei essere SOL.
John Stone

1
ah si .. se non puoi usare serializzare allora. puoi sempre manipolare il DOM e creare un modulo con quegli elementi e serializzarlo, ma ... probabilmente sarebbe più pulito semplicemente digitare manualmente i campi.
Adam Tuliper - MSFT

@TahaRehmanSiddiqui serialize funziona davvero in IE, cosa non funziona? Ricevi un errore?
Adam Tuliper - MSFT

ogni proprietà del mio modello esce nulla
Taha Rehman Siddiqui

@ TahaRehmanSiddiqui il "nome" dei campi del modulo corrisponde ai nomi delle proprietà del modello?
MongooseNX

0

Se usi MVC 5 leggi questa soluzione!

Conosco la domanda specificamente chiamata per MVC 3, ma mi sono imbattuto in questa pagina con MVC 5 e volevo pubblicare una soluzione per chiunque altro nella mia situazione. Ho provato le soluzioni di cui sopra, ma non hanno funzionato per me, il filtro di azione non è mai stato raggiunto e non sono riuscito a capire perché. Sto usando la versione 5 nel mio progetto e ho finito con il seguente filtro di azione:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Filters;

namespace SydHeller.Filters
{
    public class ValidateJSONAntiForgeryHeader : FilterAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            string clientToken = filterContext.RequestContext.HttpContext.Request.Headers.Get(KEY_NAME);
            if (clientToken == null)
            {
                throw new HttpAntiForgeryException(string.Format("Header does not contain {0}", KEY_NAME));
            }

            string serverToken = filterContext.HttpContext.Request.Cookies.Get(KEY_NAME).Value;
            if (serverToken == null)
            {
                throw new HttpAntiForgeryException(string.Format("Cookies does not contain {0}", KEY_NAME));
            }

            System.Web.Helpers.AntiForgery.Validate(serverToken, clientToken);
        }

        private const string KEY_NAME = "__RequestVerificationToken";
    }
}

- Prendi nota delle librerie using System.Web.Mvce using System.Web.Mvc.Filters, non delle httplibrerie (penso che sia una delle cose che è cambiata con MVC v5. -

Quindi applica il filtro [ValidateJSONAntiForgeryHeader] alla tua azione (o controller) e dovrebbe essere chiamato correttamente.

Nella mia pagina di layout proprio sopra </body>ho@AntiForgery.GetHtml();

Infine, nella mia pagina Razor, eseguo la chiamata ajax come segue:

var formForgeryToken = $('input[name="__RequestVerificationToken"]').val();

$.ajax({
  type: "POST",
  url: serviceURL,
  contentType: "application/json; charset=utf-8",
  dataType: "json",
  data: requestData,
  headers: {
     "__RequestVerificationToken": formForgeryToken
  },
     success: crimeDataSuccessFunc,
     error: crimeDataErrorFunc
});

1
Stai recuperando manualmente tutti i valori del modulo? Perché no data: $("#the-form").serialize()?
Sinjai

1
@Sinjai dovrei guardare di nuovo il mio codice, ma credo di fare anche qualche altra elaborazione. ".serialize ()" funzionerebbe anche se ti
servissero

Nessun problema, ero solo curioso.
Sinjai
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.