首先写一个简单的webservice:
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld(string name) {
return "Hello, " + name;
}
}
在RoR项目里,添加app/apis/test_api.rb:
class TestApi < ActionWebService::API::Base
api_method :HelloWorld, :expects => [{:name => :string}], :returns => [:string]
end
这是RoR里面通用的webservice元信息描述。
添加app/controllers/test_controller.rb:
class TestController < ApplicationController
web_client_api :test, :soap, "http://localhost/test/Service.asmx",
:namespace => "http://tempuri.org/",
:soap_action_base => "http://tempuri.org",
:driver_options=>{:default_encodingstyle => SOAP::EncodingStyle::ASPDotNetHandler::Namespace }
def hello
render_text test.HelloWorld("Li Jie")
end
end
:soap_action_base选项是一个修补,不加这个选项会产生SOAPAction头错误。
运行服务器,在浏览器中访问/test/hello,发现名字为空。经过长时间调试,发现.Net在解析SOAP消息体时,不能处理这种命名空间:
<n1:HelloWorld xmlns:n1="http://tempuri.org/"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<name xsi:type="xsd:string">Li Jie</name>
</n1:HelloWorld>
把n1去掉就行了。不过这部分实现在rubylib/soap/rpc/proxy.rb里面,实在不方便修改。为了让这个测试通过,暂时做了点小修改:
def route(req_header, req_body, reqopt, resopt)
req_env = ::SOAP::SOAPEnvelope.new(req_header, req_body)
unless reqopt[:envelopenamespace].nil?
set_envelopenamespace(req_env, reqopt[:envelopenamespace])
end
reqopt[:external_content] = nil
conn_data = marshal(req_env, reqopt)
if ext = reqopt[:external_content]
mime = MIMEMessage.new
ext.each do |k, v|
mime.add_attachment(v.data)
end
mime.add_part(conn_data.send_string + "\r\n")
mime.close
conn_data.send_string = mime.content_str
conn_data.send_contenttype = mime.headers['content-type'].str
end
conn_data.send_string.gsub!(/:n1/, '')
conn_data.send_string.gsub!(/n1:/, '')
conn_data = @streamhandler.send(@endpoint_url, conn_data,
reqopt[:soapaction])
if conn_data.receive_string.empty?
return nil
end
unmarshal(conn_data, resopt)
end
加粗的2行是我添加的代码,勉强可以让它工作,不过显然不是正确的方法。
不知道是不是.Net库里面的BUG。