zoukankan      html  css  js  c++  java
  • 自定义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的消息。这个就必须用到了。
    代码
     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[0as 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(nullnull0null, 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, null0null, 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[0as 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[0as 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
  • 相关阅读:
    DS4700磁盘阵列的控制器微码升级操作记录(收录百度文库)
    Android 解决布局无法对齐的情况
    android 模仿大众点评团购卷列表多余3条时折叠,点击时显示剩余全部的功能
    android 解决ScrollView中的子布局不能够填充整个ScrollView的情况。
    Android在代码中设置控件的drawableLeft,drawableRight,drawableTop,drawableBottom。
    android RadioGroup中设置selector后出现多个别选中的RadioButton的解决办法
    Android 动态的给Button、TextView、ImageView等控件设置了background后,再设置padding属性时该属性不起作用
    Android Universal Image Loader java.io.FileNotFoundException: http:/xxx/lxx/xxxx.jpg
    Android2.3系统 自定义的PopupWindow在实例化时报空指针异常
    android精品开源项目整理
  • 原文地址:https://www.cnblogs.com/lovebanyi/p/1961258.html
Copyright © 2011-2022 走看看