Невозможно установить для типа содержимого значение 'application / json' в jQuery.ajax

106

Когда у меня есть этот код

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

в Fiddler я вижу следующий необработанный запрос

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

Но я пытаюсь установить тип содержимого из application / x-www-form-urlencoded в application / json . Но этот код

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

Создает странный запрос (который я вижу в 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

Это почему? Что такое OPTIONS, когда он должен быть там POST? И где мой тип контента установлен на application / json? И параметры запроса ушли почему-то.

ОБНОВЛЕНИЕ 1

На стороне сервера у меня действительно простой сервис RESTful.

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

Но почему-то не могу вызвать этот метод с параметрами.

ОБНОВЛЕНИЕ 2

Извините, что не ответил так долго.

Я добавил эти заголовки в свой ответ сервера

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

Это не помогло, у меня метод не разрешает ошибку с сервера.

Вот что говорит мой скрипач

введите описание изображения здесь

Итак, теперь я могу быть уверен, что мой сервер принимает POST, GET, OPTIONS (если заголовки ответов работают так, как я ожидал). Но почему «Метод не разрешен»?

В ответе WebView от сервера (вы можете увидеть ответ Raw на картинке выше) выглядит так

введите описание изображения здесь

Виталий Корсаков
источник
2
вам следует попробовать метод JSON.stringfy ()
Амритпал Сингх
Смотри сюда. У меня это работает очень хорошо: stackoverflow.com/questions/9754767/…
Fanda
У меня точно такая же проблема, но я работаю с NodeJS в качестве бэкэнда, также я установил, что все запросы OPTION не только принимаются, но и заставляют отвечать 200 на все запросы OPTION, чтобы остальные петиции работали, как ожидалось без ответа ...
HeberLZ
1
Привет @VitaliiKorsakov. Вы решили свою проблему? Я столкнулся с той же проблемой, т.е. не могу изменить contentType.
worldterminator
1
У меня была такая же проблема, и она только что заработала ... решение находится в ответе на этой странице: stackoverflow.com/questions/20295080/ ... Подводя итог: «При использовании contentType: 'application / json' вы будете нельзя полагаться на заполнение $ _POST. $ _POST заполняется только для типов содержимого с кодировкой формы. Таким образом, вам нужно читать свои данные из необработанных входных данных PHP ".. Теперь я вижу, что вы не используете php на сервере сторона, но, надеюсь, эта информация поможет в некотором роде.
Сара

Ответы:

91

Казалось бы, удаление http://из опции url гарантирует отправку правильного заголовка HTTP POST.

Я не думаю, что вам нужно полностью указывать имя хоста, просто используйте относительный URL-адрес, как показано ниже.

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

Пример моего, который работает:

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

Возможно, связано: jQuery $ .ajax (), $ .post отправка "OPTIONS" как REQUEST_METHOD в Firefox

Изменить: после некоторых дополнительных исследований я обнаружил, что заголовок OPTIONS используется, чтобы узнать, разрешен ли запрос из исходного домена. Используя fiddler, я добавил следующее в заголовки ответов с моего сервера.

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

Как только браузер получил этот ответ, он отправил правильный запрос POST с данными json. Казалось бы, тип содержимого по умолчанию с URL-адресом считается безопасным и поэтому не подвергается дополнительным междоменным проверкам.

Похоже, вам нужно будет добавить ранее упомянутые заголовки в ответ вашего сервера на запрос OPTIONS. Вы, конечно же, должны настроить их так, чтобы разрешать запросы от определенных доменов, а не от всех.

Я использовал следующий jQuery, чтобы проверить это.

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

Ссылки:

Майк Уэйд
источник
Я хочу ослабить связь между клиентом и сервером. Сервер - это служба RESTful, и все клиенты этой службы должны знать URL-адрес.
Виталий Корсаков
Не могли бы вы подробнее рассказать в своем сообщении о сценарии этого вопроса? Если ваши клиенты будут находиться в разных доменах, вы можете столкнуться с одинаковыми проблемами происхождения.
Майк Уэйд,
Я разместил дополнительную информацию о сервере. Сейчас сервер и клиент находятся на локальном хосте, но отличаются портом. Позже они, скорее всего, будут на разных доменах.
Виталий Корсаков
Похоже, что проблема, с которой вы столкнулись, связана с той же политикой происхождения, возможно, стоит посмотреть на jsonp и вопрос, на который я ссылался в своем ответе, в дополнение к этим вопросам, связанным со ссылками . Руководство по кросс-домену jquery - у меня нет большого опыта работы с междоменными запросами, но, надеюсь, эти ссылки будут вам полезны.
Майк Уэйд
Я не думаю, что это проблема, потому что все работает нормально, когда я не передаю никаких параметров, а тип содержимого - application / x-www-form-urlencoded. Но мне не нужен POST-запрос, если я не могу передать какие-либо параметры.
Виталий Корсаков
42

Я могу показать вам, как я это использовал

  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;
                }
            }
        });
    }
Амритпал Сингх
источник
То же, что и в следующем ответе. Я не могу не указать url-адрес сервера, на котором размещены все сервисные функции,
Виталий Корсаков
@VitaliiKorsakov, я ушел, вы разобрались со своей проблемой.
Амритпал Сингх
Спасибо за ответ! Не могу поверить, что это где-то еще не прописано. Конечно, похоже, что JQuery отправит json, когда вы укажете тип json, но я думаю, что нет ...
Джейсон Гоэмаат
1
@JasonGoemaat параметр dataType в jQuery используется только для анализа тела возвращенного ответа. Если вы прочтете документацию, то увидите, что это даже не нужно. Значение по умолчанию для dataType - умное предположение. Ваша проблема в том, что атрибут данных в jquery не настраивается. Вы не можете сказать, как jquery должен анализировать объект данных. Вот почему вам нужно сериализовать json раньше. Потому что jquery сериализуется только в url-form-encode
Лоик Фор-Лакруа,
12

Итак, все, что вам нужно сделать, чтобы это сработало, - это добавить:

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

в качестве поля для вашего почтового запроса, и он будет работать.

Коди Жак
источник
api.jquery.com/jquery.ajax Если вы посмотрите в документации, там написано, что без его указания по умолчанию используется 'application / x-www-form-urlencoded; charset = UTF-8 '(вот почему это происходит. Idk, почему просто установка contentType не работает. Возможно, вы захотите проверить, какая у вас версия jQuery, и обновить ее, если вы используете старую версию).
Cody Jacques
Это не работает. Хотя у меня есть type: "POST", это отправка OPTIONS.
user9645
5

Я узнал эти экраны, я использую CodeFluentEntities, и у меня есть решение, которое мне тоже подходит.

Я использую эту конструкцию:

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

как видите, если я использую

contentType: "",

или

contentType: "text/plain", //chrome

Все нормально работает.

Я не уверен на 100%, что это все, что вам нужно, потому что я также изменил заголовки.

Алексей Авдеев
источник
5

Если вы используете это:

contentType: "application/json"

AJAX не отправляет на сервер параметры GET или POST .... не знаю почему.

Сегодня мне потребовались часы, чтобы выучить это.

Просто используйте:

$.ajax(
  { url : 'http://blabla.com/wsGetReport.php',
    data : myFormData, type : 'POST', dataType : 'json', 
    // contentType: "application/json", 
    success : function(wsQuery) { }
  }
)
Луис Артуро Эрике Гуахала
источник
1
к сожалению, правильный ответ для меня. Опустите contentType и просто используйте dataType для обхода мусора CORS OPTIONS, который многие службы просто не реализуют должным образом. Так раздражает.
Umopepisdn
2

Я нашел решение этой проблемы здесь . Не забудьте разрешить глагол OPTIONS в обработчике службы приложений IIS.

Работает отлично. Спасибо, Андре Педросо. :-)

Фанда
источник
1

Я была такая же проблема. Я запускаю приложение java rest на сервере jboss. Но я думаю, что решение похоже на веб-приложение ASP .NET.

Firefox выполняет предварительный вызов вашего сервера / URL-адреса отдыха, чтобы проверить, какие параметры разрешены. Это запрос "OPTIONS", на который ваш сервер не отвечает соответствующим образом. Если на этот вызов OPTIONS дан правильный ответ, выполняется второй вызов, который является фактическим запросом POST с содержимым json.

Это происходит только при выполнении междоменного вызова. В вашем случае вызов ' http://localhost:16329/Hello' вместо вызова URL-адреса в том же домене '/ Hello'

Если вы намереваетесь выполнить междоменный вызов, вам необходимо улучшить свой класс обслуживания отдыха с помощью аннотированного метода, который поддерживает HTTP-запрос «OPTIONS». Это соответствующая реализация java:

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

Итак, я предполагаю, что в .NET вам нужно добавить дополнительный метод, аннотированный

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

где установлены следующие заголовки

.header("Access-Control-Allow-Origin", "*")
        .header("Access-Control-Allow-Headers", "Content-Type")
        .header("Access-Control-Allow-Methods", "POST, OPTIONS")
Винсент
источник
0

У меня есть решение для отправки данных JSON по запросу POST через jquery ajax. Я использовал код ниже

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


        });
    });

Я использовал 'Content-Type': 'text/plain'в заголовке для отправки необработанных данных json.
Потому что, если мы используем Content-Type: 'application/json'методы запроса, преобразованные в OPTION, но использование Content-Type: 'test/plain'метода не преобразуется и остается как POST. Надеюсь, это кому-нибудь поможет.

Рахул Апараджит
источник
3
На самом деле он не преобразуется в OPTION, он отправляет предварительный запрос CORS, чтобы проверить, разрешен ли POST. Когда это не возвращается правильно, POST не происходит.
Umopepisdn
0

Привет, эти две строчки у меня сработали.

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

Спасибо, Прашант

Прашант Кумар
источник