这个非常简单,运行这个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!");
}
});
}
答案 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上只返回那些。