寺委书记

Good good study, day day up!

导航

Silverlight跨域调用gSoap/Java web service 以及wsdl文件的修改

Posted on 2012-01-11 03:37  MonkChen  阅读(1873)  评论(3)    收藏  举报

应用场景: silverlight客户端 调用gSoap编写的web service,遇到两个问题

1)Silverlight跨域调用web service的安全限制

2)vs2010添加gSoap web service,wsdl解析遇到问题,无法生成代理类代码

 

经过干小时摸索,解决问题,好记性不如烂笔头,特此记下以备忘。

 

解决方案:

  1. 查了众多资料,都说要把ServiceReferences.ClientConfig文件复制到IIS的根目录或者网站的根目录,进一步研究发现是要放在web service端的目录下,而不是客户端。可是我的gSoap服务宿主是控制台程序,起初放到去无任何效果,依然无法调用。

        后来发现ie地址栏输入http://localhost:8090/ServiceReferences.ClientConfig显示的依然是wsdl代码,客户端无法获取该配置文件导致的。于是猛然想起    gSoap的http_get函数,该函数作用就是响应客户端的get请求,将wsdl文件发送出去,http://localhost:8090/ServiceReferences.ClientConfig不也是get请求们,在http_get函数里设断点验证,没错!接下来就好办了,改造http_get, 代码如下:(对http_get函数不了解的同学请查阅gSoap user guide)

     

int  http_get(struct   soap   *soap) 

    string fileName = "ns.wsdl";
    
    if(strstr(soap->msgbuf,"clientaccesspolicy.xml")!=NULL){
        fileName = "clientaccesspolicy.xml";
    }//红色乃添加的代码
    FILE*fd = NULL;
    fd = fopen(fileName.c_str(), "rb"); //open WSDL file to copy
    if (!fd)
    {
        return 404//return HTTP not found error
    }
    soap->http_content = "text/xml";  //HTTP header with text /xml content
    soap_response(soap,SOAP_FILE);
    for(;;)
    {
        size_t r = fread(soap->tmpbuf,1sizeof(soap->tmpbuf), fd);
        if (!r)
        {
                break;
        }
        if (soap_send_raw(soap, soap->tmpbuf, r))
        {
                break//cannot send, but little we can do about that
        }
    }
    fclose(fd);
    soap_end_send(soap);
    return SOAP_OK; 
}

别忘了把clientaccesspolicy.xml拷到程序目录,当然也可以指定路径。 问题解决!同理,

 

     2.gSoap服务端有个结构体是这么定义的:

typedef struct string_array
{
 xsd__string *__ptr;
 xsd__int __size;
}; 

 用于传递字符串数组,例如设备支持的云台协议名称,当然你也可以用一个字符串,用某个符号做分割,可是我还是喜欢用数组。

gSoap自动生成的wsdl,相应的描述如下:

<complexType name="ArrayOfstring">
   <complexContent>
    <restriction base="SOAP-ENC:Array">
     <sequence>
      <element name="item" type="xsd:string" minOccurs="0" maxOccurs="unbounded" nillable="true"/>
     </sequence>
     <attribute ref="SOAP-ENC:arrayType" WSDL:arrayType="xsd:string[]"/>
    </restriction>
   </complexContent>
  </complexType>

用Silverlight引用web service时老是报错,首条警告信息就是不支持arrayType,google一圈没什么有价值的资料,问题依旧无法解决。想起java写的ws就有返回数组的,为什么SL就能引用成功?看了一下java写的ws的wsdl,关于数组的描述如下:

<xs:complexType name="getDevUserOfOrgResponse">
<xs:sequence>
  <xs:element maxOccurs="unbounded" minOccurs="0" name="return" type="tns:sipDevUser" /> 
  </xs:sequence>
  </xs:complexType>

果然有所差距啊,看来问题出在wsdl上,手动改吧,改后的版本:

<complexType name="ArrayOfstring">
     <sequence>
      <element name="item" type="xsd:string" minOccurs="0" maxOccurs="unbounded" nillable="true"/>
     </sequence>
  </complexType>

保存,启动ws, sl添加引用,通过-----:D 看到了代理类里面可爱的数组了。。。

 

附录:

Silverlight项目的ServiceReferences.ClientConfig文件

<configuration >
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="PatCsgServiceSoap" maxBufferSize="65536" maxReceivedMessageSize="65536">
          <security mode="None" />
        </binding>
        <binding name="Service" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
          <security mode="None" />
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://192.168.1.19:8090" binding="basicHttpBinding"
        bindingConfiguration
="PatCsgServiceSoap" contract="WsPatCsg.ServicePortType"
        name
="PatCsgService_EndPoint" />
    </client>
  </system.serviceModel>

</configuration>

 

clientaccesspolicy.xml

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="*">
        <domain uri="*"/>
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>