Der Inhaltstyp kann in jQuery.ajax nicht auf 'application / json' gesetzt werden

106

Wenn ich diesen Code habe

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

in Fiddler kann ich folgende rohe Anfrage sehen

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

Ich versuche jedoch, den Inhaltstyp von application / x-www-form-urlencoded auf application / json festzulegen . Aber dieser Code

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

Erzeugt eine seltsame Anfrage (die ich in Fiddler sehen kann)

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

Warum ist das so? Was ist OPTIONEN, wenn es dort POST sein soll? Und wo ist mein Inhaltstyp auf application / json eingestellt? Und Anforderungsparameter sind aus irgendeinem Grund weg.

UPDATE 1

Auf der Serverseite habe ich einen wirklich einfachen RESTful-Service.

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

Aber aus irgendeinem Grund kann ich diese Methode nicht mit Parametern aufrufen.

UPDATE 2

Entschuldigung, dass Sie nicht so lange geantwortet haben.

Ich habe diese Header zu meiner Serverantwort hinzugefügt

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

Es hat nicht geholfen, ich habe Methode Fehler vom Server nicht erlaubt .

Hier ist, was mein Geiger sagt

Geben Sie hier die Bildbeschreibung ein

Jetzt kann ich sicher sein, dass mein Server POST, GET, OPTIONS akzeptiert (wenn die Antwortheader wie erwartet funktionieren). Aber warum "Methode nicht erlaubt"?

In WebView sieht die Antwort vom Server (siehe Raw- Antwort auf dem Bild oben) folgendermaßen aus

Geben Sie hier die Bildbeschreibung ein

Vitalii Korsakov
quelle
2
Sie sollten JSON.stringfy () Methode versuchen
Amritpal Singh
Schau hier. Das funktioniert bei mir sehr gut: stackoverflow.com/questions/9754767/…
Fanda
Ich habe genau das gleiche Problem, aber ich arbeite mit NodeJS als Backend. Außerdem habe ich festgelegt, dass alle OPTION-Anforderungen nicht nur akzeptiert werden, sondern dass auf alle OPTION-Anforderungen eine Antwort von 200 erzwungen wird, damit der Rest der Petitionen wie erwartet funktioniert ohne Antwort ...
HeberLZ
1
Hallo @VitaliiKorsakov. Hast du dein Problem gelöst? Ich habe das gleiche Problem, dh ich kann den Inhaltstyp nicht ändern.
Weltterminator
1
Ich hatte das gleiche Problem und habe es gerade zum Laufen gebracht . Die Lösung finden Sie in der Antwort auf dieser Seite: stackoverflow.com/questions/20295080/… .. um es zusammenzufassen: "Wenn Sie contentType: 'application / json' verwenden, werden Sie Sie können sich nicht darauf verlassen, dass $ _POST ausgefüllt wird. $ _POST wird nur für formularcodierte Inhaltstypen ausgefüllt. Daher müssen Sie Ihre Daten aus PHP-Roheingaben lesen. ".. Ich sehe, dass Sie jetzt kein PHP auf dem Server verwenden Seite, aber hoffentlich helfen diese Informationen irgendwie.
Sarah

Antworten:

91

Es scheint, dass das Entfernen http://aus der URL-Option sicherstellt, dass der richtige HTTP-POST-Header gesendet wird.

Ich glaube nicht, dass Sie den Namen des Hosts vollständig qualifizieren müssen. Verwenden Sie einfach eine relative URL wie unten.

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

Ein Beispiel von mir, das funktioniert:

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

Möglicherweise verwandt: jQuery $ .ajax (), $ .post sendet "OPTIONS" als REQUEST_METHOD in Firefox

Bearbeiten: Nach einigen weiteren Recherchen habe ich herausgefunden, dass der OPTIONS-Header verwendet wird, um herauszufinden, ob die Anforderung von der Ursprungsdomäne zulässig ist. Mit Fiddler habe ich den Antwortheadern von meinem Server Folgendes hinzugefügt.

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

Sobald der Browser diese Antwort erhalten hat, hat er die richtige POST-Anfrage mit JSON-Daten gesendet. Es scheint, dass der standardmäßige formularkodierte Inhaltstyp als sicher angesehen wird und daher keinen zusätzlichen domänenübergreifenden Überprüfungen unterzogen wird.

Es sieht so aus, als müssten Sie die zuvor genannten Header zu Ihrer Serverantwort auf die OPTIONS-Anforderung hinzufügen. Sie sollten sie natürlich so konfigurieren, dass Anforderungen von bestimmten Domänen und nicht von allen zugelassen werden.

Ich habe die folgende jQuery verwendet, um dies zu testen.

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

Verweise:

Mike Wade
quelle
Ich möchte die Kopplung zwischen Client und Server verlieren. Der Server ist ein RESTful-Dienst, und alle Clients dieses Dienstes sollten die URL dazu kennen.
Vitalii Korsakov
Können Sie in Ihrem Beitrag weitere Details zum Szenario dieser Frage angeben? Wenn sich Ihre Kunden in verschiedenen Domänen befinden, können Probleme mit demselben Ursprung auftreten.
Mike Wade
Ich habe zusätzliche Informationen zur Serverseite gepostet. Momentan befinden sich Server und Client beide auf localhost, unterscheiden sich jedoch im Port. Später werden sie höchstwahrscheinlich auf verschiedenen Domänen sein.
Vitalii Korsakov
Es scheint, dass das Problem, mit dem Sie konfrontiert sind, mit der gleichen Ursprungsrichtlinie zu tun hat. Es könnte sich lohnen, sich jsonp und die Frage anzusehen, auf die ich in meiner Antwort zusätzlich zu diesen Fragen im Zusammenhang mit Links verwiesen habe . jquery domänenübergreifender Leitfaden - Ich habe nicht viel Erfahrung mit domänenübergreifenden Anfragen, aber hoffentlich sind diese Links für Sie von Nutzen.
Mike Wade
Ich denke nicht, dass dies ein Problem ist, da alles gut funktioniert, wenn ich keine Parameter übergebe und der Inhaltstyp application / x-www-form-urlencoded ist. Ich benötige jedoch keine POST-Anfrage, wenn ich keine Parameter übergeben konnte.
Vitalii Korsakov
41

Ich kann Ihnen zeigen, wie ich es benutzt habe

  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;
                }
            }
        });
    }
Amritpal Singh
quelle
Das gleiche wie in der nächsten Antwort. Ich kann keine URL für den Server angeben, auf dem alle Servicefunktionen gehostet werden
Vitalii Korsakov
@VitaliiKorsakov Ich bin weggegangen, hast du dein Problem gelöst?
Amritpal Singh
Danke für die Antwort! Ich kann nicht glauben, dass dies nicht woanders geschrieben ist. Es scheint sicher, dass JQuery json posten würde, wenn der von Ihnen angegebene Typ 'json' ist, aber ich denke nicht ...
Jason Goemaat
1
@JasonGoemaat Der Parameter dataType in jQuery wird nur zum Analysieren des zurückgegebenen Antwortkörpers verwendet. Wenn Sie die Dokumentation lesen, werden Sie feststellen, dass sie nicht einmal benötigt wird. Der Standardwert für dataType ist intelligentes Erraten. Ihr Problem ist, dass das Datenattribut in jquery nicht konfigurierbar ist. Sie können nicht sagen, wie jquery das Datenobjekt analysieren soll. Deshalb müssen Sie json vorher serialisieren. Weil jquery nur zur URL-Form-Codierung serialisiert
Loïc Faure-Lacroix
12

Alles, was Sie tun müssen, damit dies funktioniert, ist hinzuzufügen:

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

als Feld für Ihre Post-Anfrage und es wird funktionieren.

Cody Jacques
quelle
api.jquery.com/jquery.ajax Wenn Sie in der Dokumentation nachsehen, heißt es, dass ohne Angabe standardmäßig 'application / x-www-form-urlencoded; charset = UTF-8 '(weshalb dies geschieht. Idk, warum das Festlegen von contentType nicht funktioniert. Möglicherweise möchten Sie überprüfen, welche Version von jQuery Sie haben, und aktualisieren, wenn Sie eine alte Version verwenden).
Cody Jacques
Das funktioniert nicht. Obwohl ich habe type: "POST", sendet es OPTIONS.
user9645
5

Ich habe diese Bildschirme erkannt, verwende CodeFluentEntities und habe eine Lösung, die auch für mich funktioniert.

Ich benutze diese Konstruktion:

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

wie Sie sehen können, wenn ich benutze

contentType: "",

oder

contentType: "text/plain", //chrome

Alles funktioniert gut.

Ich bin mir nicht 100% sicher, ob es alles ist, was Sie brauchen, weil ich auch die Header geändert habe.

Alexey Avdeyev
quelle
5

Wenn Sie dies verwenden:

contentType: "application/json"

AJAX sendet keine GET- oder POST-Parameter an den Server. Ich weiß nicht warum.

Ich habe heute Stunden gebraucht, um es zu lernen.

Benutz einfach:

$.ajax(
  { url : 'http://blabla.com/wsGetReport.php',
    data : myFormData, type : 'POST', dataType : 'json', 
    // contentType: "application/json", 
    success : function(wsQuery) { }
  }
)
Luis Arturo Erique Guajala
quelle
1
leider die richtige antwort für mich. Lassen Sie contentType weg und verwenden Sie einfach dataType, um den Müll von CORS OPTIONS zu umgehen, den viele Dienste einfach nicht richtig implementieren. So nervig.
Umopepisdn
2

Ich habe hier die Lösung für dieses Problem gefunden . Vergessen Sie nicht, VerbOPTIONEN im IIS App Service Handler zuzulassen.

Funktioniert gut. Vielen Dank, André Pedroso. :-)

Fanda
quelle
1

Ich hatte das gleiche Problem. Ich führe eine Java Rest App auf einem JBoss Server aus. Aber ich denke, die Lösung ist auf einer ASP .NET-Webanwendung ähnlich.

Firefox ruft vorab Ihre Server- / Ruhe-URL auf, um zu überprüfen, welche Optionen zulässig sind. Dies ist die "OPTIONS" -Anforderung, auf die Ihr Server nicht entsprechend antwortet. Wenn dieser OPTIONS-Aufruf korrekt beantwortet wird, wird ein zweiter Aufruf ausgeführt, bei dem es sich um die eigentliche "POST" -Anforderung mit JSON-Inhalt handelt.

Dies geschieht nur, wenn ein domänenübergreifender Anruf ausgeführt wird. In Ihrem Fall rufen Sie ' http://localhost:16329/Hello' auf, anstatt einen URL-Pfad unter derselben Domain '/ Hello' aufzurufen.

Wenn Sie einen domänenübergreifenden Anruf tätigen möchten, müssen Sie Ihre Rest-Service-Klasse mit einer kommentierten Methode erweitern, die eine http-Anforderung "OPTIONS" unterstützt. Dies ist die entsprechende Java-Implementierung:

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

Ich denke, in .NET müssen Sie eine zusätzliche Methode hinzufügen, die mit Anmerkungen versehen ist

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

Dabei werden die folgenden Überschriften gesetzt

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

Ich habe die Lösung erhalten, die JSON-Daten per POST-Anfrage über jquery ajax zu senden. Ich habe unten Code verwendet

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


        });
    });

Ich habe 'Content-Type': 'text/plain'im Header verwendet, um die rohen JSON-Daten zu senden.
Denn wenn wir Content-Type: 'application/json'die in OPTION konvertierten Anforderungsmethoden verwenden, wird die Verwendung Content-Type: 'test/plain'der Methode jedoch nicht konvertiert und bleibt als POST erhalten. Hoffentlich hilft das jemandem.

Rahul Aparajit
quelle
3
Es wird nicht wirklich in OPTION konvertiert, sondern es wird eine CORS-Preflight-Anforderung gesendet, um zu überprüfen, ob der POST zulässig ist. Wenn dies nicht richtig zurückkommt, findet der POST nicht statt.
Umopepisdn
0

Hallo, diese beiden Zeilen haben bei mir funktioniert.

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

Danke, Prashant

Prashant Kumar
quelle