Silverlight_Rest_WCF系列之三:PUT和DELETE
我们在上篇文章中讲过WebClient不支持PUT,DELETE.
那么WebRequest支持PUT和DELETE吗??
于是我们修改PUT代码为:
webRequest.ContentType = "application/json";
webRequest.Method = "PUT";
结果还是一样的错误,细心的读者如果反编译过WebClient的话,可以看到内部的实现就是:
using System;
protected virtual WebRequest GetWebRequest(Uri address)
{
WebRequest webRequest = WebRequest.Create(address);
this.CopyHeadersTo(webRequest);
HttpWebRequest httpWebRequest = webRequest as HttpWebRequest;
。。。
return webRequest;
}
原来WebClient不支持PUT和DELETE是因为WebRequest.Create(address)返回的WebRequest不支持PUT和DELETE啊。
事到如今摆在面前有两个方案。。
1:不支持就不要用它,就简单的用GET,POST两个Method就好了,用URL来区别就可以了,比如
2:试试还有没有其他的WebRequest支持PUT,DELETE,比如HttpWebRequest,。
当然了用1方案的没任何问题,用2方案的就要google下了。
在Silverlight中使用WebRequestCreator就可以设置PUT,DELETE了。
new Uri("http://localhost:19598/ProductService.svc/Product"));
于是将PUT的代码修改为:
WebRequest webRequest =WebRequestCreator.ClientHttp.Create(
new Uri("http://localhost:19598/ProductService.svc/Product"));
webRequest.ContentType = "application/json";
webRequest.Method = "PUT";
webRequest.BeginGetRequestStream(requestAsyncCallback =>
{
Stream requestStream = webRequest.EndGetRequestStream(requestAsyncCallback);
JsonObject jo = new JsonObject();
jo["Id"] = Guid.NewGuid().ToString();
jo["Name"] = "test";
string jsonString = jo.ToString();
byte[] buffer = System.Text.Encoding.Unicode.GetBytes(jsonString);
requestStream.Write(buffer, 0, buffer.Length);
requestStream.Close();
webRequest.BeginGetResponse(responseAsyncCallback =>
{
WebResponse webResponse = webRequest.EndGetResponse(responseAsyncCallback);
using (StreamReader reader = new StreamReader(webResponse.GetResponseStream()))
{
string result = reader.ReadToEnd();
MessageBox.Show(result);
}
}, null);
}, null);
#endregion
这里还是会抛出SecurityException。主要原因是PUT和DELETE操作需要服务端授权,于是将
clientaccesspolicy.xml的代码修改为:
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-methods="*" http-request-headers="*">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
主要是设置<allow-from http-methods="*" http-request-headers="*">.
ok,我们再次尝试调用PUT。
在MessageBox.Show(result);这句代码抛出异常,异常为跨线程访问无效。
在silverlight中创建UI控件的是一个线程,也叫做UI线程,
silverlight使用其他的线程异步的调用服务,然后在其他的线程中尝试调用UI线程的MessageBox.Show,
针对跨线程访问无效有两种通用的方法。
1:使用Dispatcher对象。
2:使用System.Threading.SynchronizationContext对象保存线程的同步上下文.
在这里为了方便,我就直接
{
MessageBox.Show(result);
});
完整源码:/Files/LoveJenny/2011-05-09/RestWCF.rar
好了,今天就到此为止,下篇文章要封装调用Rest服务的方式,毕竟不可能每次调用服务都Copy这么多代码吧,下回分解。。