Как использовать метод HttpWebRequest GET w / ContentType = "application / json" - PullRequest
3 голосов
/ 10 января 2011

Это очень просто, запустите этот пример Silverlight4 с закомментированным свойством ContentType, и вы получите ответ от моего сервиса в xml.Теперь раскомментируйте свойство и запустите его, и вы получите исключение ProtocolViolationException. Служба возвращает данные в формате JSON.

#if DEBUG
                Address = "http://localhost.:55437/Services/GetFoodDescriptionsLookup(2100)";
#else
                Address = "http://stephenpattenconsulting.com/Services/GetFoodDescriptionsLookup(2100)";
#endif

Uri httpSite = new Uri(Address);

HttpWebRequest wreq = 
(HttpWebRequest)WebRequestCreator.ClientHttp.Create(httpSite);

//wreq.ContentType = "application/json"; // Wrong
wreq.Accept = "application/json"; // Right

wreq.BeginGetResponse((cb) =>
{
    HttpWebRequest rq = cb.AsyncState as HttpWebRequest;
    HttpWebResponse resp = rq.EndGetResponse(cb) as HttpWebResponse; // Exception
    StreamReader rdr = new StreamReader(resp.GetResponseStream());
    string result =  rdr.ReadToEnd(); 
    rdr.Close();
}, wreq);

Новое исключение

System.NotSupportedException не было обработано пользователемкод Message = "" StackTrace: в System.Net.Browser.AsyncHelper.BeginOnUI (SendOrPostCallback beginMethod, состояние объекта) в System.Net.Browser.BrowserHttpWebRequest.EndGetResponse (IAsyncResult asyncResult) в. com.web.Web 0 (IAsyncResult cb) в System.Net.Browser.BrowserHttpWebRequest. <> C _DisplayClassd.b__b (объект state2) в System.Threading.QueueUserWorkItemCallback.WaitCallback_Context (состояние объекта) в объекте System.ThecutionThree(ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта, логическое значение ignoreSyncCtx) в System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem () в System.Threading.ThreadPoolWorkuetem.Threading. ThreadPoolWaitCallback.PerformWaitCallback () InnerException: System.NotSupportedException Message = указанный метод не поддерживается.StackTrace: в System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse (IAsyncResult asyncResult) в System.Net.Browser.BrowserHttpWebRequest. <> C _DisplayClass5.b_ 4 (объект sendShelser для объекта).. <> c _DisplayClass2.b__0 (Object sendState) InnerException:

РАБОТАЕТ СЕЙЧАС

Исключение, которое я получаю, связано с хаком, который я использую дляполучите Fiddler, чтобы показать адаптер обратной петли, т.е. http://localhost.:55437/Services/GetFoodDescriptionsLookup(2100), обратите внимание на дополнительную точку после слова localhost.

Вот и все!

Я знаю, чтовсе думают, это можно было бы решить, я бы включил некоторые из этих деталей ... например, флаг отладки, который изменяет URI, я удалил большую часть кода, чтобы его было легче читать на SO, думая, что проблема была всетевой стек.Трудные уроки усвоены.

Спасибо всем, кто нашел время, чтобы заняться этим, как в stackoverflow, так и в автономном режиме.

Для полноты я добавил функцию jQuery, которая заставляла меня думать все это время, что мне нужно былоустановка «тип контента» вместо «принять» в приложении SL4.(ПРОЧИТАЙТЕ ДОКУМЕНТЫ!)

function CallService(serviceUrl, data, callback) {
    $.ajax({
        url: serviceUrl,
        data: data,
        dataType: 'json',
        contextType: "application/json", 
        cache: false,
        success: callback,
        error: function (msg) {
            alert("Request Failed!");
        }
    });
}

Ответы [ 4 ]

1 голос
/ 12 января 2011

Ответ Гленна Блока, кажется, уже говорит об этом, но я думаю, что он был недостаточно ясен.

В заголовке Content-Type указывается тип данных в теле POST или теле ответа HTTP

Ваш HTTP-запрос не является ни одним из этих . Это запрос GET без какого-либо тела. Вот почему вы получаете исключение нарушения протокола - запросы GET не могут иметь заголовок Content-Type, потому что по определению они не имеют никакого содержимого.

Ваш запрос Fiddler работает просто потому, что WCF очень удобен для клиентов с ошибками. Ошибка исходит из сетевого стека Silverlight, который отказывается отправлять неработающий запрос.

Давайте возьмем это сверху: вы хотите получить обратно данные JSON. Это выполняется с помощью заголовка Accept , который сообщает серверу, какие данные вы хотите получить обратно. Поэтому замените это

wreq.ContentType = "application/json"; 

с этим

wreq.Accept = "application/json"; 

и вы получите данные JSON с сервера.

1 голос
/ 11 января 2011

Если вы окончательно определите, что это проблема в Silverlight HttpWebRequest, т. Е. В нем может быть ошибка или чрезмерно глупая проверка безопасности, которая не позволяет обрабатывать текстовые / json-ответы, один разумный (если раздражающий) обходной путь может быть Оболочка в javascript, чтобы сделать запрос, используя объект XMLHttpRequest, а затем вернуть результаты в Silverlight. Раздражает, но можно.

1 голос
/ 12 января 2011

Стивен, установка типа контента должна разрешать отправку JSON, а не его получение. Есть несколько способов сделать это. Вы можете поддерживать как JSON, так и XML или только JSON. Если все, что вам нужно, это поддерживать JSON, то вы можете сделать это, установив свойство ResponseFormat в атрибуте WebGet для операции службы.

Если вы хотите поддерживать как JSON, так и XML, то вам нужно либо включить автоматический выбор формата в службе и отправить заголовок принятия "application / json", в противном случае вы может использовать параметр строки формата в строке запроса, а служба должна использовать свойство WebOperationContext.OutgoingResponse.Format.

Вот пост , который охватывает различные способы сделать это со стороны сервера. Если вы идете по пути поддержки автоматического выбора формата, вам нужно установить заголовок accept запроса HttpWebRequest в «application / json»

0 голосов
/ 10 января 2011

Можете ли вы опубликовать детали для конечной точки WCF?Если он возвращает XAML, единственный способ получить JSON - это если он настроен на.Первоначальный запрос просто запрашивает URL, он не указывает «режим», поэтому я предполагаю, что WCF по умолчанию использует XML.Должна быть либо конкретная конечная точка для ответов JSON, либо параметр в WCF, чтобы возвращать только эти ответы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...