Не получен ответ JSON с использованием приложения типа контента/JSON iOS

Мой клиент предоставил мне услугу REST, для которой я должен получить ответ JSON для своего кода iOS. Я использую content-type как «application/json», но по умолчанию он почему-то принимается как «text/html». Я перепроверил это в клиенте REST в своем браузере Mozilla, используя «application/json» для content-type в разделе заголовка, и я смог увидеть правильный ответ. При использовании приведенного ниже кода я получаю ошибку 400 от сервера. Я всегда мог видеть, что "text/html" используется как часть ответа 400 по умолчанию.

NSString * strBodyOnlineStart = [NSString stringWithFormat:@"&email=***@***.com&deviceCode=*****&password_value=***"];

      NSURL *urlOnlineStart = [NSURL
                          URLWithString:@"http://local.server/xxxxx"];
        NSMutableURLRequest *requestOnlineStart = [NSMutableURLRequest
                                                   requestWithURL:urlOnlineStart];


        [requestOnlineStart setValue:@"application/json" forHTTPHeaderField:@"Accept"];
        [requestOnlineStart setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

        [requestOnlineStart setHTTPMethod:@"POST"];
        NSData *requestBodyOnlineStart = [strBodyOnlineStart
                                          dataUsingEncoding:NSUTF8StringEncoding];
        [requestOnlineStart setHTTPBody:requestBodyOnlineStart];

Ниже приведен ответ, который я получаю от сервера


person Leo Joseph    schedule 26.04.2014    source источник
comment
Попробуйте изменить application/json на application/json; charset=utf-8 и попробуйте закодировать тело запроса с помощью NSUTF8StringEncoding   -  person startswithaj    schedule 26.04.2014
comment
Почему вы используете кодировку строки NSUTF32StringEncoding? Вы пытались использовать NSUTF8StringEncoding?   -  person Vlad Papko    schedule 26.04.2014
comment
добавив application/json; charset=utf-8 Я все еще получил ответ (текст/html типа контента, код состояния 400). и @Visput Только кодировка nsutf8. я напечатала это по ошибке   -  person Leo Joseph    schedule 26.04.2014
comment
Веб-служба ASP не кодирует ответ json перед его отправкой. Проверьте API еще раз   -  person Malloc    schedule 26.04.2014
comment
Какой API? это API кода iOS или API сервера? и ответ приходит правильно в клиенте Firefox REST @Malloc   -  person Leo Joseph    schedule 26.04.2014
comment
Если возможно, попробуйте запросить ASP.net API непосредственно из браузера и посмотрите, возвращает ли он ДЕЙСТВИТЕЛЬНЫЙ ответ json. Если да, то проверьте свой закодированный запрос. проверьте этот аналогичный пост: stackoverflow.com/a/7981511/602257   -  person Malloc    schedule 26.04.2014
comment
Поскольку это метод POST, я попытался использовать клиент REST и получил правильный ответ JSON. Также я внедрил код из той ссылки, которую вы упомянули. Все тот же ответ. @Маллок   -  person Leo Joseph    schedule 26.04.2014
comment
Я много раз решал подобные вещи в прошлом. Не похоже, чтобы обсуждался каждый бит реализации. Это может быть другое поле заголовка, которое отправляют остальные клиент и браузер, которого нет в приведенном выше коде ObjC. Было бы полезно увидеть полностью рабочие заголовки запроса/ответа и пример тела от остального клиента. Между прочим... Charles proxy и fiddler - отличные инструменты для решения подобных задач!   -  person Tom Pace    schedule 26.04.2014
comment
Насколько я понимаю, fiddler предназначен для Windows, не могли бы вы предоставить ссылку на его загрузку для Mac OSX? Также в клиенте REST (Firefox) мы отправляем только тип содержимого как application/json @TomPace.   -  person Leo Joseph    schedule 26.04.2014
comment
@LeoJoseph Мне пришлось купить лучшее приложение скрипача, эквивалентное Mac, это прокси-сервер Charles. Я не могу вспомнить, есть ли у него бесплатная пробная версия. Проверьте мой новый опубликованный ответ на предмет предложения по типу контента и формату тела.   -  person Tom Pace    schedule 26.04.2014


Ответы (2)


Я создал множество серверных REST-сервисов и множество мобильных клиентских приложений, чтобы получить к ним доступ и бесчисленное количество раз сталкивался с подобными проблемами. Так что я знаю вашу боль, и я решил эти проблемы с помощью собственного набора инструментов (мне нравится Fiddler для Windows и Charles для Mac) и узнал много причин неудач.

Первое наблюдение:

Без полной информации о работающей паре запрос-ответ и неудачной паре запрос-ответ найти официальное решение невозможно. Но я почти уверен, что если бы вы их предоставили, официальное решение было бы простым.

Тестирование

Чтобы проверить вашу проблему, я установил клиент REST в Firefox и настроил новый сервис на моей машине разработки. Кроме того, я использовал Charles Proxy в OS X с функцией редактирования запроса для настройки необработанного запроса.

Я перепроверил это в клиенте REST в своем браузере Mozilla, используя «application/json» для типа контента в разделе заголовка, и я увидел правильный ответ.

Странно, что вы говорите, что это сработало. Я попробовал это, и сервер не смог проанализировать значения тела. Серверная платформа, которую я использую, не ASP.NET, но я просто придерживаюсь стандартного ожидаемого поведения любой платформы. Возможно, ваш REST-клиент на самом деле не отправлял заголовок. Интересно, переключили ли вы заголовок на какое-то произвольное значение, например application/notjson, и посмотрите, работает ли он до сих пор (тогда я бы предположил, что это переопределение клиента REST).

Вероятная причина

Как указано в приведенной выше цитате, вы создаете впечатление, что хотите получить application/json в заголовке ответа Content-Type, и кажется, что вы думаете, что должны отправить заголовок Content-Type в запросе, чтобы соответствовать этому ответу. Это не должно быть необходимым. Сервер должен иметь возможность получать ваш запрос в стандартном формате application/x-www-form-urlencoded, типичном для серверов, и отвечать в формате JSON так, как вы ожидаете.

Обычно веб-серверы не естественным образом принимают json в качестве формата тела запроса, и аналогичным образом они обычно не получают входящий запрос Content-Type приложения/json. Но я видел случаи, когда они это делали.

В любом случае отправка запроса с конфликтующими форматами Content-Type и body определенно является неудачной настройкой.

Я обнаружил, что мой тест сервера отвечает с помощью JSON, используя ваше тело &email=***@***.com&deviceCode=*****&password_value=***, после переключения заголовка на application/x-www-form-urlencoded, application/json. Типичная доброта.

Код

Попробуйте закомментировать следующую строку:

    [requestOnlineStart setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

или изменить его на:

    [requestOnlineStart setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
person Tom Pace    schedule 26.04.2014
comment
попытка с application/notjson изменила правила игры... Я учил, что заголовок был ошибкой. Большое спасибо - person Leo Joseph; 28.04.2014
comment
@LeoJoseph круто, я рад, что смог помочь. Не могли бы вы уточнить, что было вашим фактическим исправлением, чтобы решить вашу проблему? :) - person Tom Pace; 29.04.2014

Давайте попробуем (см. мой комментарий):

// replace strBodyOnlineStart NSDictionary
// NSString * strBodyOnlineStart = [NSString stringWithFormat:@"&email=***@***.com&deviceCode=*****&password_value=***"];
NSDictionary *requestObj = @{
                             @"email":  your email,
                             @"passwordValue": your password,
                             };

// Can you try jsonRequest with NSJSONSerialization framework (iOS framework default).
NSData *jsonRequest = [NSJSONSerialization dataWithJSONObject:strBodyOnlineStart options:0 error:&error];

// your url has "/" value at the end or not???
NSString *url = @"http://local.server/xxxxx/";
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:jsonRequest];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

//try set value like this
[request setValue:[NSString stringWithFormat:@"%d", [jsonRequest length]] forHTTPHeaderField:@"Content-Length"];

// Hope this format helps you. 
person nmh    schedule 26.04.2014
comment
Я получаю sigabrt после NSData *jsonRequest = ... Может быть, потому что до этой строки я не получаю никакого ответа JSON для анализа. - person Leo Joseph; 26.04.2014