[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;
}
}