如何使用HttpWebRequest GET方法w / ContentType =“application / json”

时间:2011-01-10 05:59:51

标签: silverlight wcf json httpwebrequest

这个非常简单,运行这个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未被用户代码处理   消息=“”   堆栈跟踪:        在System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod,Object state)        在System.Net.Browser.BrowserHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)        at com.patten.silverlight.ViewModels.WebRequestLiteViewModel.b_ 0(IAsyncResult cb)        在System.Net.Browser.BrowserHttpWebRequest。<> c _DisplayClassd.b__b(对象state2)        在System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(对象状态)        at System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback callback,Object state,Boolean ignoreSyncCtx)        在System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()        在System.Threading.ThreadPoolWorkQueue.Dispatch()        在System.Threading。 ThreadPoolWaitCallback.PerformWaitCallback()   InnerException:System.NotSupportedException        消息=不支持指定的方法。        堆栈跟踪:             在System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)             在System.Net.Browser.BrowserHttpWebRequest。<> c _DisplayClass5.b_ 4(Object sendState)             在System.Net.Browser.AsyncHelper。<> c _DisplayClass2.b__0(Object sendState)        InnerException:

现在工作

我得到的例外是由于我用来让Fiddler显示环回适配器(即http://localhost.:55437/Services/GetFoodDescriptionsLookup(2100)的黑客攻击,请注意单词localhost之后的额外DOT。

就是这样!

我知道每个人都在想什么,这本来可以解决它我会包含一些这些细节..比如改变URI的调试标志,我删除了大部分代码,以便更容易阅读SO,认为问题出在网络堆栈中。学到了很多教训。

感谢所有花时间参与此事的人,包括stackoverflow和离线。

为了完整性,我添加了jQuery函数,让我一直在思考,在SL4应用程序中我需要设置“content-type”而不是“accept”。 (阅读文件!)

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 个答案:

答案 0 :(得分:1)

如果你最终确定它在Silverlight HttpWebRequest中是一个问题,也就是说,它可能有一个错误或过于愚蠢的安全检查,使其无法处理text / json响应,一个合理的(如果讨厌)解决方法可能是shell使用XMLHttpRequest对象发出javascript来发出请求,然后将结果返回给Silverlight。讨厌,但可能。

答案 1 :(得分:1)

Stephen,设置内容类型是允许SENDING JSON,而不是接收它。有几种方法可以做到这一点。您既可以支持JSON和XML,也可以只支持JSON。如果您只想支持JSON,那么可以通过在WebGet属性上设置ResponseFormat属性来执行此操作。

如果要同时支持JSON和XML,则需要在服务上启用自动格式选择并发送“application / json”的接受标头,否则你 可以在查询字符串中使用格式字符串参数,并让服务使用WebOperationContext.OutgoingResponse.Format属性。

这是一个post,涵盖了从服务器端执行此操作的各种方法。如果你选择支持自动格式选择的路线,那么你需要将HttpWebRequest的accept标题设置为“application / json”

答案 2 :(得分:1)

Glenn Block的回答似乎已经说明了这一点,但我想这还不够清楚。

Content-Type标头告诉POST正文或HTTP响应正文中的数据类型

您的HTTP请求不是这些。这是一个没有任何身体的GET请求。这就是您获得协议违规异常的原因 - GET请求不能具有Content-Type标头,因为根据定义它们没有任何内容。

您的Fiddler请求正在运行,因为WCF非常适合有错误的客户端。该错误来自Silverlight网络堆栈内部,该堆栈拒绝发送损坏的请求。

让我们从顶部开始:您想要获取JSON数据。这是使用 Accept 标头完成的,该标头告诉服务器您想要获取哪种数据。因此,请替换此

wreq.ContentType = "application/json"; 

用这个

wreq.Accept = "application/json"; 

您将从服务器获取JSON数据。

答案 3 :(得分:0)

您可以发布WCF终点的详细信息吗?如果它返回XAML,获取JSON的唯一方法是它是否配置为。初始请求只是请求一个URL,它没有指定“模式”,所以我假设WCF默认为XML。应该有一个特定的端点去寻找JSON响应,或者一个设置在WCF上只返回那些。