[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
里面的
比如说 GetUser()的方法 但是可能因为权限不过,所以要抛出一个xml的消息。这个就必须用到了。
{
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;
}
}