Impossibile impostare il tipo di contenuto su "application / json" in jQuery.ajax


106

Quando ho questo codice

$.ajax({
    type: 'POST',
    //contentType: "application/json",
    url: 'http://localhost:16329/Hello',
    data: { name: 'norm' },
    dataType: 'json'
});

in Fiddler posso vedere la seguente richiesta grezza

POST http://localhost:16329/Hello HTTP/1.1
Host: localhost:16329
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost:14693/WebSite1/index.html
Content-Length: 9
Origin: http://localhost:14693
Pragma: no-cache
Cache-Control: no-cache

name=norm

Ma quello che sto cercando è di impostare il tipo di contenuto da application / x-www-form-urlencoded ad application / json . Ma questo codice

$.ajax({
    type: "POST",
    contentType: "application/json",
    url: 'http://localhost:16329/Hello',
    data: { name: 'norm' },
    dataType: "json"
});

Genera una strana richiesta (che posso vedere in Fiddler)

OPTIONS http://localhost:16329/Hello HTTP/1.1
Host: localhost:16329
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Origin: http://localhost:14693
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Pragma: no-cache
Cache-Control: no-cache

Perché? Cos'è OPTIONS quando dovrebbe essere POST lì? E dov'è il mio tipo di contenuto impostato su application / json? E i parametri di richiesta sono andati per qualche motivo.

AGGIORNAMENTO 1

Sul lato server ho un servizio RESTful davvero semplice.

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class RestfulService : IRestfulService
{
    [WebInvoke(
        Method = "POST",
        UriTemplate = "Hello",
        ResponseFormat = WebMessageFormat.Json)]
    public string HelloWorld(string name)
    {
        return "hello, " + name;
    }
}

Ma per qualche motivo non posso chiamare questo metodo con i parametri.

AGGIORNAMENTO 2

Scusa per non aver risposto così a lungo.

Ho aggiunto queste intestazioni alla mia risposta del server

 Access-Control-Allow-Origin: *
 Access-Control-Allow-Headers: Content-Type
 Access-Control-Allow-Methods: POST, GET, OPTIONS

Non ha aiutato, ho il metodo non consentito l' errore dal server.

Ecco cosa dice il mio violinista

inserisci qui la descrizione dell'immagine

Quindi, ora posso essere sicuro che il mio server accetta POST, GET, OPTIONS (se le intestazioni di risposta funzionano come mi aspetto). Ma perché "Metodo non consentito"?

In WebView la risposta dal server (puoi vedere la risposta grezza nell'immagine sopra) ha questo aspetto

inserisci qui la descrizione dell'immagine


2
dovresti provare il metodo JSON.stringfy ()
Amritpal Singh

Guarda qui. Questo funziona molto bene per me: stackoverflow.com/questions/9754767/…
Fanda

Sto avendo lo stesso identico problema, ma sto lavorando con NodeJS come backend, inoltre ho impostato tutte le richieste OPTION non solo per essere accettate ma per forzare una risposta 200 su tutte le richieste OPTION in modo che il resto delle petizioni funzioni come previsto senza risposta ...
HeberLZ

1
Ciao @VitaliiKorsakov. Hai risolto il tuo problema? Incontro lo stesso problema, cioè non posso modificare contentType.
worldterminator

1
Ho avuto lo stesso problema e appena ottenuto che funziona .. la soluzione è nella risposta in questa pagina: stackoverflow.com/questions/20295080/... ..per Riassumendo: "Quando si utilizza contentType: 'application / json' si non essere in grado di fare affidamento sul fatto che $ _POST venga popolato. $ _POST è popolato solo per i tipi di contenuto codificato in forma. Pertanto, devi leggere i tuoi dati dall'input non elaborato PHP ".. Vedo che ora non stai usando php sul server lato ma si spera che queste informazioni aiutino in qualche modo.
Sarah

Risposte:


91

Sembrerebbe che la rimozione http://dall'opzione url garantisca l'invio dell'intestazione HTTP POST corretta.

Non penso che sia necessario qualificare completamente il nome dell'host, basta usare un URL relativo come di seguito.

   $.ajax({
      type: "POST",
      contentType: "application/json",
      url: '/Hello',
      data: { name: 'norm' },
      dataType: "json"
   });

Un mio esempio che funziona:

        $.ajax({
            type: "POST",
            url: siteRoot + "api/SpaceGame/AddPlayer",
            async: false,
            data: JSON.stringify({ Name: playersShip.name, Credits: playersShip.credits }),
            contentType: "application/json",
            complete: function (data) {
            console.log(data);
            wait = false;
        }
    });

Possibilmente correlato: jQuery $ .ajax (), $ .post che invia "OPTIONS" come REQUEST_METHOD in Firefox

Modifica: dopo ulteriori ricerche ho scoperto che l'intestazione OPTIONS viene utilizzata per scoprire se la richiesta dal dominio di origine è consentita. Utilizzando Fiddler, ho aggiunto quanto segue alle intestazioni di risposta dal mio server.

 Access-Control-Allow-Origin: *
 Access-Control-Allow-Headers: Content-Type
 Access-Control-Allow-Methods: POST, GET, OPTIONS

Una volta che il browser ha ricevuto questa risposta, ha quindi inviato la richiesta POST corretta con i dati json. Sembrerebbe che il tipo di contenuto predefinito con codifica URL sia considerato sicuro e quindi non venga sottoposto a controlli interdominio aggiuntivi.

Sembra che dovrai aggiungere le intestazioni menzionate in precedenza alla risposta del tuo server alla richiesta OPTIONS. Ovviamente dovresti configurarli per consentire richieste da domini specifici piuttosto che da tutti.

Ho usato il seguente jQuery per testarlo.

$.ajax({
   type: "POST",
   url: "http://myDomain.com/path/AddPlayer",
   data: JSON.stringify({
      Name: "Test",
       Credits: 0
   }),
   //contentType: "application/json",
   dataType: 'json',
   complete: function(data) {
       $("content").html(data);
  }
});​

Riferimenti:


Voglio perdere l'accoppiamento tra client e server. Il server è un servizio RESTful e tutti i client di questo servizio dovrebbero conoscerne l'URL.
Vitalii Korsakov

Puoi fornire qualche dettaglio in più nel tuo post sullo scenario di questa domanda? Se i tuoi clienti si trovano su domini diversi, potresti riscontrare gli stessi problemi di origine.
Mike Wade

Ho pubblicato ulteriori informazioni sul lato server. In questo momento server e client entrambi su localhost ma differiscono per la porta. In seguito molto probabilmente saranno su domini diversi.
Vitalii Korsakov

Sembra che il problema che stai riscontrando abbia a che fare con la stessa politica di origine, potrebbe valere la pena guardare jsonp e la domanda a cui ho collegato nella mia risposta oltre a questi link - domanda correlata . jquery guida interdominio - Non ho molta esperienza con le richieste interdominio, ma spero che quei link ti saranno utili.
Mike Wade

Non penso che questo sia un problema perché tutto funziona bene quando non passo alcun parametro e il tipo di contenuto è application / x-www-form-urlencoded. Ma non ho bisogno della richiesta POST se non sono riuscito a passare alcun parametro.
Vitalii Korsakov

41

Posso mostrarti come l'ho usato

  function GetDenierValue() {
        var denierid = $("#productDenierid").val() == '' ? 0 : $("#productDenierid").val();
        var param = { 'productDenierid': denierid };
        $.ajax({
            url: "/Admin/ProductComposition/GetDenierValue",
            dataType: "json",
            contentType: "application/json;charset=utf-8",
            type: "POST",
            data: JSON.stringify(param),
            success: function (msg) {
                if (msg != null) {
                    return msg.URL;
                }
            }
        });
    }

La stessa cosa della prossima risposta. Non posso non specificare l'URL del server in cui sono ospitate tutte le funzioni del servizio
Vitalii Korsakov

@VitaliiKorsakov sono andato via, hai risolto il tuo problema.
Amritpal Singh

Grazie per la risposta! Non riesco a credere che questo non sia spiegato da qualche altra parte. Sembra che JQuery pubblichi json quando il tipo specificato è "json", ma immagino di no ...
Jason Goemaat

1
@JasonGoemaat il parametro dataType in jQuery viene utilizzato solo per analizzare il corpo della risposta restituita. Se leggi la documentazione, vedrai che non è nemmeno necessaria. Il valore predefinito per dataType è ipotesi intelligente. Il tuo problema è che l'attributo data in jquery non è configurabile. Non puoi dire come jquery dovrebbe analizzare l'oggetto dati. Ecco perché devi serializzare json prima. Perché jquery serializza solo in url-form-encode
Loïc Faure-Lacroix

12

Quindi tutto ciò che devi fare affinché funzioni è aggiungere:

headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
}

come campo per la tua richiesta di post e funzionerà.


api.jquery.com/jquery.ajax Se guardi nella documentazione dice che senza specificarlo il valore predefinito è 'application / x-www-form-urlencoded; charset = UTF-8 '(ecco perché sta succedendo. Idk perché l'impostazione di contentType non funziona però. Potresti voler controllare quale versione di jQuery hai e aggiornare se sei su una vecchia versione).
Cody Jacques

Questo non funziona. Anche se l'ho fatto type: "POST", sta inviando OPTIONS.
user9645

5

Ho riconosciuto quegli schermi, sto usando CodeFluentEntities e ho una soluzione che ha funzionato anche per me.

Sto usando quella costruzione:

$.ajax({
   url: path,
   type: "POST",
   contentType: "text/plain",
   data: {"some":"some"}
}

come puoi vedere, se uso

contentType: "",

o

contentType: "text/plain", //chrome

Tutto funziona bene.

Non sono sicuro al 100% che sia tutto ciò di cui hai bisogno, perché ho anche cambiato le intestazioni.


5

Se usi questo:

contentType: "application/json"

AJAX non invierà parametri GET o POST al server ... non so perché.

Mi ci sono volute ore per impararlo oggi.

Basta usare:

$.ajax(
  { url : 'http://blabla.com/wsGetReport.php',
    data : myFormData, type : 'POST', dataType : 'json', 
    // contentType: "application/json", 
    success : function(wsQuery) { }
  }
)

1
purtroppo la risposta corretta per me. Ometti contentType e usa semplicemente dataType per bypassare la spazzatura CORS OPTIONS che molti servizi semplicemente non implementano correttamente. Così fastidioso.
Umopepisdn

2

Ho trovato la soluzione per questo problema qui . Non dimenticare di consentire le OPZIONI del verbo sul gestore del servizio app IIS.

Funziona bene. Grazie André Pedroso. :-)


1

Ho avuto lo stesso problema. Sto eseguendo un'app java rest su un server jboss. Ma penso che la soluzione sia simile su una webapp ASP .NET.

Firefox effettua una chiamata preliminare al tuo server / URL di rest per verificare quali opzioni sono consentite. Questa è la richiesta "OPZIONI" a cui il tuo server non risponde di conseguenza. Se questa chiamata OPTIONS viene risposto correttamente, viene eseguita una seconda chiamata che è l'effettiva richiesta "POST" con contenuto json.

Questo accade solo quando si esegue una chiamata interdominio. Nel tuo caso chiamando " http://localhost:16329/Hello" invece di chiamare un percorso URL sotto lo stesso dominio "/ Hello"

Se intendi effettuare una chiamata interdominio, devi migliorare la tua classe di servizio di riposo con un metodo annotato che supporta una richiesta http "OPTIONS". Questa è l'implementazione java corrispondente:

@Path("/rest")
public class RestfulService {

    @POST
    @Path("/Hello")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.TEXT_PLAIN)
    public string HelloWorld(string name)
    {
        return "hello, " + name;
    }

//THIS NEEDS TO BE ADDED ADDITIONALLY IF MAKING CROSS-DOMAIN CALLS

    @OPTIONS
    @Path("/Hello")
    @Produces(MediaType.TEXT_PLAIN+ ";charset=utf-8")
    public Response checkOptions(){
        return Response.status(200)
        .header("Access-Control-Allow-Origin", "*")
        .header("Access-Control-Allow-Headers", "Content-Type")
        .header("Access-Control-Allow-Methods", "POST, OPTIONS") //CAN BE ENHANCED WITH OTHER HTTP CALL METHODS 
        .build();
    }
}

Quindi immagino che in .NET devi aggiungere un metodo aggiuntivo annotato con

[WebInvoke(
        Method = "OPTIONS",
        UriTemplate = "Hello",
        ResponseFormat = WebMessageFormat.)]

dove sono impostate le seguenti intestazioni

.header("Access-Control-Allow-Origin", "*")
        .header("Access-Control-Allow-Headers", "Content-Type")
        .header("Access-Control-Allow-Methods", "POST, OPTIONS")

0

Ho la soluzione per inviare i dati JSON tramite richiesta POST tramite jquery ajax. Ho usato il codice di seguito

    var data = new Object();
    data.p_clientId = 4;
    data =  JSON.stringify(data);

    $.ajax({
      method: "POST",
      url: "http://192.168.1.141:8090/api/Client_Add",
      data: data,
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'text/plain'
    }
    })
      .done(function( msg ) {
        alert( "Data Saved: " + msg );
      });


        });
    });

Ho usato 'Content-Type': 'text/plain'nell'intestazione per inviare i dati json non elaborati.
Perché se usiamo Content-Type: 'application/json'i metodi di richiesta convertiti in OPTION, ma utilizzando Content-Type: 'test/plain'il metodo non viene convertito e rimane come POST. Si spera che questo possa aiutare qualcuno.


3
Non si sta realmente convertendo in OPTION, sta inviando una richiesta di verifica preliminare CORS per verificare se il POST è consentito. Quando questo non torna correttamente, il POST non viene eseguito.
Umopepisdn

0

Ciao Queste due righe hanno funzionato per me.

contentType: "application / json; charset = utf-8", dataType: "json"

 $.ajax({
            type: "POST",
            url: "/v1/candidates",
            data: obj,
            **contentType:"application/json; charset=utf-8",
            dataType:"json",**
            success: function (data) {
                table.row.add([
                    data.name, data.title
                ]).draw(false);
            }

Grazie, Prashant

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.