I think I hit a problem when using C# client to consume Google App Engine Webservice. The Google App Engine code I use is here. This is how the python script on server would look like:
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
import logging
from StringIO import StringIO
import traceback
import xmlrpclib
from xmlrpcserver import XmlRpcServer
class Application:
def __init__(self):
pass
def getName(self,meta):
return 'example'
class XMLRpcHandler(webapp.RequestHandler):
rpcserver = None
def __init__(self):
self.rpcserver = XmlRpcServer()
app = Application()
self.rpcserver.register_class('app',app)
def post(self):
request = StringIO(self.request.body)
request.seek(0)
response = StringIO()
try:
self.rpcserver.execute(request, response, None)
except Exception, e: 开发者_运维问答
logging.error('Error executing: '+str(e))
for line in traceback.format_exc().split('\n'):
logging.error(line)
finally:
response.seek(0)
rstr = response.read()
self.response.headers['Content-type'] = 'text/xml'
self.response.headers['Content-length'] = "%d"%len(rstr)
self.response.out.write(rstr)
application = webapp.WSGIApplication(
[('/xmlrpc/', XMLRpcHandler)],
debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
The client side ( in Python) is this:
import xmlrpclib
s = xmlrpclib.Server('http://localhost:8080/xmlrpc/')
print s.app.getName()
I have no problem in using Python client to retrieve values from Google App Engine, but I do have difficulties in using a C# client to retrieve the values. The error I got was 404 method not found
when I am trying to GetResponse
from the web request.
This is my code
var request = (HttpWebRequest)WebRequest.Create("http://localhost:8080/xmlrpc/app");
request.Method = "GET";
request.ContentLength = 0;
request.ContentType = "text/xml";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) //404 method not found error here.
{
}
Edit: For end points, I've tried:
- http://localhost:8080/xmlrpc
- http://localhost:8080/xmlrpc/
- http://localhost:8080/xmlrpc/app
- http://localhost:8080/xmlrpc/app/
But none works
I think it must be that the url is wrong, but I don't know how to get it right. Any idea?
I guess what happens is that your request sent using HttpWebRequest is missing actual content; which should be your rpc method information in xml format. Please check if code below would work for you; it should send request to http://localhost:8080/xmlrpc/ and dump resulting xml into console.
// send request
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:8080/xmlrpc/");
request.Method = "POST";
request.ContentType = "text/xml; encoding=utf-8";
string content = "<?xml version='1.0'?><methodCall><methodName>app.getName</methodName><params></params></methodCall>";
byte[] contentBytes = System.Text.UTF8Encoding.UTF8.GetBytes(content);
request.ContentLength = contentBytes.Length;
using (Stream stream = request.GetRequestStream())
{
stream.Write(contentBytes, 0, contentBytes.Length);
}
// get response
WebResponse response = request.GetResponse();
XmlDocument xmlDoc = new XmlDocument();
using (Stream responseStream = response.GetResponseStream())
{
xmlDoc.Load(responseStream);
Console.WriteLine(xmlDoc.OuterXml);
}
hope this helps, regards
In addition to the excellent answer posted here, one can also use xml-rpc.net to do the job.
Here's the code on the server side, assuming that getName now takes a string
parameter:
def getName(self,meta, keyInput):
return keyInput
And this would be the C# Client code, by making use of xml-rpc.net:
[XmlRpcUrl("http://localhost:8080/xmlrpc")]
public interface IMath : IXmlRpcProxy
{
[XmlRpcMethod("app.getName")]
string GetName(string number);
}
public string GetName(string keyInput)
{
var mathProxy = XmlRpcProxyGen.Create<IMath>();
mathProxy.Url = "http://localhost:8080/xmlrpc/";
return mathProxy.GetName(keyInput);
}
Hope this helps everyone who's struggling to make rpc call to GAE from C# client.
The regular expression in your App Engine app for the endpoint is exactly '/xmlrpc/', which is what you use in the Python test, but in your C# client you're using '/xmlrpc/app', which isn't mapped to anything.
精彩评论