EasyText, EasyLicense 的作者, https://github.com/EasyHelper Good Good Study,Day Day Up.

 

Silverlight_Rest_WCF系列之三:PUT和DELETE

我们在上篇文章中讲过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这么多代码吧,下回分解。。

 

posted @ 2011-05-09 20:58  LoveJenny  阅读(4596)  评论(3编辑  收藏  举报
EasyText, EasyLicense 的作者, https://github.com/EasyHelper Good Good Study,Day Day Up.