我们在上篇文章中讲过WebClient不支持PUT,DELETE.
那么WebRequest支持PUT和DELETE吗??
于是我们修改PUT代码为:
WebRequest webRequest
=
WebRequest.Create(
"
http://localhost:19598/ProductService.svc/Product
"
);
webRequest.ContentType
=
"
application/json
"
;
webRequest.Method
=
"
PUT
"
;
结果还是一样的错误,细心的读者如果反编译过WebClient的话,可以看到内部的实现就是:
//
System.Net.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来区别就可以了,比如
http://...createproduct/
http://...updateproduct/,
http://...deleteproduct/
2:试试还有没有其他的WebRequest支持PUT,DELETE,比如HttpWebRequest,。
当然了用1方案的没任何问题,用2方案的就要google下了。
在Silverlight中使用WebRequestCreator就可以设置PUT,DELETE了。
WebRequest webRequest
=
WebRequestCreator.ClientHttp.Create(
new
Uri(
"
http://localhost:19598/ProductService.svc/Product
"
));
于是将PUT的代码修改为:
#region
使用WebRequest
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的代码修改为:
<?
xml version
=
"
1.0
"
encoding
=
"
utf-8
"
?>
<
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对象保存线程的同步上下文.
在这里为了方便,我就直接
this
.Dispatcher.BeginInvoke(()
=>
{
MessageBox.Show(result);
});
完整源码:/Files/LoveJenny/2011-05-09/RestWCF.rar
好了,今天就到此为止,下篇文章要封装调用Rest服务的方式,毕竟不可能每次调用服务都Copy这么多代码吧,下回分解。。