自定义Proxy 来做 rest wcf的客户端 与 WebChannelFactory<>的bug

[ServiceContract(Name="Profile")]
    public interface IProfile
    {
        [OperationContract]
        [WebGet(UriTemplate = "")]
        ProfileInfo Get();

        [OperationContract]
        [WebInvoke(UriTemplate = "", Method = "PUT")]
        ProfileInfo Update(ProfileInfo instance);

    }

    

        var httpRequest = (HttpWebRequest)WebRequest.Create(url);
            Client.AuthorizeRequest(httpRequest, Authorization.AccessToken);

            WebChannelFactory<IProfile> f = new WebChannelFactory<IProfile>(new Uri(url));
       
            IProfile service = f.CreateChannel();
            IClientChannel clientchanel = service as IClientChannel;
           
            try
            {
                var httpDetails = new HttpRequestMessageProperty();
                httpDetails.Headers[HttpRequestHeader.Authorization] = httpRequest.Headers[HttpRequestHeader.Authorization];
                    ProfileInfo info = new ProfileInfo();
                    info.Name="xxx";
                    var info2 = service.Update(info);
                    var test = service.Get();
                    var info3 = service.Update(info);
                    var test2 =  service.Get();
               
            }

我们可以看到的是 一但我用 Get方法来获取一次数据的话。
Update方法就无法把数据post出去了。很神奇的一个bug.

具体的原因就不清楚了。

 

为了可以解决这个问题。我们必须自己弄一个Proxy
里面的

Response类是出错时的对象,这样你就可以进行出错的处理了,可以自己抛出异常。跟服务端的Response的属性必须一样
比如说 GetUser()的方法 但是可能因为权限不过,所以要抛出一个xml的消息。这个就必须用到了。

 

 

ExpandedBlockStart.gif 代码
  public   class  WebShopProxy < T >  : RealProxy
    {
        
public  WebShopProxy( string  baseUrl)
            : 
base ( typeof (T))
        {
            BaseUrl 
=  baseUrl;
            
        }

        
public  AuthorizationState Authorization
        {
            
get ;
            
set ;
        }


        
private   string  BaseUrl
        {
            
get ;
            
set ;
        }

        
private   static  Dictionary < Type,  string >  TypeNameCache  =   new  Dictionary < Type,  string > ();
        
private   string  GetServiceName(Type t)
        {
            
if  (TypeNameCache.ContainsKey(t))
            {
                
return  TypeNameCache[t];
            }
            
object [] objs  =  t.GetCustomAttributes( typeof (ServiceContractAttribute),  false );
            
if  (objs  != null   &&  objs.Length > 0 )
            {
                
string  name  =   "" ;
                ServiceContractAttribute attribute 
=  objs[ 0 as  ServiceContractAttribute;
                
if  ( ! string .IsNullOrEmpty(attribute.Name))
                {
                    name 
=  attribute.Name;
                    TypeNameCache.Add(t, name);
                    
return  name;
                }
                
else
                {
                    
string  msg  =   string .Format( " Type:{0} ServiceContract Attribute does not have name property " , t.Name);
                    
throw   new  Exception(msg);
                }
            }
            
else
            {
                
string  msg  =   string .Format( " Type:{0} does not have ServiceContract Attribute " , t.Name);
                
throw   new  Exception(msg);
            }
        }

        
private  WebClient WebClient  =   new  WebClient();
        
public   override  IMessage Invoke(IMessage msg)
        {

            IMethodCallMessage methodCall 
=  msg  as  IMethodCallMessage;
            
byte [] buffer  =  GetResource(methodCall);
            
return  ReturnMessage(methodCall, buffer);
        }

        
private   static  IMessage ReturnMessage(IMethodCallMessage methodCall,  byte [] buffer)
        {
            
try
            {
                
if  (buffer.Length == 0 )
                {
                    
return   new  ReturnMessage( null null 0 null , methodCall);
                }
                MemoryStream stream 
=   new  MemoryStream(buffer);
                var returnType 
=  ((System.Reflection.MethodInfo)(methodCall.MethodBase)).ReturnType;
                DataContractSerializer serizlizer 
=   new  DataContractSerializer(returnType);
                
object  o  =  serizlizer.ReadObject(stream);
                
return   new  ReturnMessage(o,  null 0 null , methodCall);
            }
            
catch  (SerializationException)
            {
                DataContractSerializer serizlizer2 
=   new  DataContractSerializer( typeof (Response));
                
try
                {
                    MemoryStream stream 
=   new  MemoryStream(buffer);
                    var response 
=  (Response)serizlizer2.ReadObject(stream);
                    
return   new  ReturnMessage( new  WebShopException(response), methodCall);
                }
                
catch  (Exception e)
                {
                    
return   new  ReturnMessage(e, methodCall);
                }
            }
        }

        
private   byte [] GetResource(IMethodCallMessage methodCall)
        {
            WebClient.Headers.Add(
" Content-Type " " application/xml; charset=utf-8 " );
            
if  (Authorization != null )
            {
                WebClient.Headers[
" Authorization " =   " oauth token= " + Authorization.AccessToken;
            }

            
string  serviceName  =  GetServiceName( typeof (T));
            
string  uritemplate  =   "" ;
            
string  url  = "" ;
            
byte [] buffer;
            
object [] webGetObjs  =  methodCall.MethodBase.GetCustomAttributes( typeof (WebGetAttribute),  false );
            
object [] webInvokeObjs  =  methodCall.MethodBase.GetCustomAttributes( typeof (WebInvokeAttribute),  false );
            
if  (webGetObjs  != null   &&  webGetObjs.Length > 0 )
            {
                WebGetAttribute attribute 
=  webGetObjs[ 0 as  WebGetAttribute;
                uritemplate 
=  attribute.UriTemplate.ToLower();
                
for  ( int  i = 0 ; i < methodCall.ArgCount; i ++ )
                {
                    
object  o  =  methodCall.GetArg(i);
                    
string  name  =   methodCall.GetArgName(i).ToLower();
                    
string  replaceName  =   " { " + name + " } " ;
                    
if  (uritemplate.IndexOf(name) !=- 1 )
                    {
                        
if  (CheckType(o))
                        {
                            uritemplate 
=  uritemplate.Replace(replaceName, HttpUtility.UrlEncode(o.ToString()));
                        }
                        
else
                        {
                            
throw   new  Exception( string .Format( " parameter {0} should be int or string type " , name));
                        }
                    }
                    
else
                    {
                        
throw   new  Exception( string .Format( " WebGet Attribute can not support parameter {0}. " , name));
                    }
                }
                url 
=  MakeUrl(serviceName, uritemplate, url);
                buffer 
=   WebClient.DownloadData(url);
            }
            
else   if  (webInvokeObjs  != null   &&  webInvokeObjs.Length > 0 )
            {
                WebInvokeAttribute attribute 
=   webInvokeObjs[ 0 as  WebInvokeAttribute;
                uritemplate 
=  attribute.UriTemplate.ToLower();
                StringBuilder postData 
=   new  StringBuilder();
                
int  warper  = 0 ;
                
for  ( int  i = 0 ; i < methodCall.ArgCount; i ++ )
                {
                    
object  o  =  methodCall.GetArg(i);
                    
string  name  =   methodCall.GetArgName(i).ToLower();
                    
string  replaceName  =   " { " + name + " } " ;
                    
if  (uritemplate.IndexOf(name) !=- 1 )
                    {
                        
if  (CheckType(o))
                        {
                           uritemplate 
=  uritemplate.Replace(replaceName, HttpUtility.UrlEncode(o.ToString()));
                        }
                        
else
                        {
                            
throw   new  Exception( string .Format( " Parameter {0} should be int or string type. " , name));
                        }
                    }
                    
else
                    {
                        
if  (warper > 0 )
                        {
                            
throw   new  Exception( " At most one body parameter can be serialized. " );
                        }

                        XmlWriterSettings settings 
=   new  XmlWriterSettings();
                        settings.Indent 
=   true ;
                        settings.OmitXmlDeclaration 
=   true ;
                        settings.NewLineOnAttributes 
=   true ;
                      
                        XmlWriter writer 
=  XmlWriter.Create(postData,settings);
                        DataContractSerializer serizlizer 
=   new  DataContractSerializer(o.GetType());
                        serizlizer.WriteObject(writer, o);
                        writer.Flush();
                        warper
++ ;
                    }
                }
                url 
=  MakeUrl(serviceName, uritemplate, url);
                
byte [] data  =  Encoding.UTF8.GetBytes(postData.ToString());
                buffer 
=   WebClient.UploadData(url, attribute.Method, data);
            }
            
else
            {
                
throw   new  Exception( " You should add webget or webinvoke attribute on this method. " );
            }
            
return  buffer;
        }

        
private   static   bool  CheckType( object  o)
        {
            
return  o  is   int   ||  o  is   string   ||  o  is   bool ;
        }

        
private   string  MakeUrl( string  serviceName,  string  uritemplate,  string  url)
        {
            
if  (uritemplate.StartsWith( " / " ))
            {
                url 
=  BaseUrl + serviceName + uritemplate;
            }
            
else
            {
                url 
=  BaseUrl + serviceName + " / " +  uritemplate;
            }
            
return  url;
        }
    }
完整的客户端在这边可以下到 http://dev.starteenwinkel.nl/doc/DotNetSDK
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值