WSDL with linked xsds are not compiled dynamically using c#

眉间皱痕 提交于 2019-12-11 08:08:52

问题


I have a following wsdl from a WCF service.

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions name="Service" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:tns="http://tempuri.org/" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex">
  <wsp:Policy wsu:Id="WSHttpBinding_IService_policy">
    <wsp:ExactlyOne>
      <wsp:All>
        <sp:SymmetricBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
          <wsp:Policy>
            <sp:ProtectionToken>
              <wsp:Policy>
                <sp:SecureConversationToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
                  <wsp:Policy>
                    <sp:RequireDerivedKeys />
                    <sp:BootstrapPolicy>
                      <wsp:Policy>
                        <sp:SignedParts>
                          <sp:Body />
                          <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
                          <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" />
                          <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" />
                          <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" />
                          <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" />
                          <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" />
                          <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" />
                        </sp:SignedParts>
                        <sp:EncryptedParts>
                          <sp:Body />
                        </sp:EncryptedParts>
                        <sp:SymmetricBinding>
                          <wsp:Policy>
                            <sp:ProtectionToken>
                              <wsp:Policy>
                                <sp:SpnegoContextToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
                                  <wsp:Policy>
                                    <sp:RequireDerivedKeys />
                                  </wsp:Policy>
                                </sp:SpnegoContextToken>
                              </wsp:Policy>
                            </sp:ProtectionToken>
                            <sp:AlgorithmSuite>
                              <wsp:Policy>
                                <sp:Basic256 />
                              </wsp:Policy>
                            </sp:AlgorithmSuite>
                            <sp:Layout>
                              <wsp:Policy>
                                <sp:Strict />
                              </wsp:Policy>
                            </sp:Layout>
                            <sp:IncludeTimestamp />
                            <sp:EncryptSignature />
                            <sp:OnlySignEntireHeadersAndBody />
                          </wsp:Policy>
                        </sp:SymmetricBinding>
                        <sp:Wss11>
                          <wsp:Policy>
                            <sp:MustSupportRefKeyIdentifier />
                            <sp:MustSupportRefIssuerSerial />
                            <sp:MustSupportRefThumbprint />
                            <sp:MustSupportRefEncryptedKey />
                          </wsp:Policy>
                        </sp:Wss11>
                        <sp:Trust10>
                          <wsp:Policy>
                            <sp:MustSupportIssuedTokens />
                            <sp:RequireClientEntropy />
                            <sp:RequireServerEntropy />
                          </wsp:Policy>
                        </sp:Trust10>
                      </wsp:Policy>
                    </sp:BootstrapPolicy>
                  </wsp:Policy>
                </sp:SecureConversationToken>
              </wsp:Policy>
            </sp:ProtectionToken>
            <sp:AlgorithmSuite>
              <wsp:Policy>
                <sp:Basic256 />
              </wsp:Policy>
            </sp:AlgorithmSuite>
            <sp:Layout>
              <wsp:Policy>
                <sp:Strict />
              </wsp:Policy>
            </sp:Layout>
            <sp:IncludeTimestamp />
            <sp:EncryptSignature />
            <sp:OnlySignEntireHeadersAndBody />
          </wsp:Policy>
        </sp:SymmetricBinding>
        <sp:Wss11 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
          <wsp:Policy>
            <sp:MustSupportRefKeyIdentifier />
            <sp:MustSupportRefIssuerSerial />
            <sp:MustSupportRefThumbprint />
            <sp:MustSupportRefEncryptedKey />
          </wsp:Policy>
        </sp:Wss11>
        <sp:Trust10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
          <wsp:Policy>
            <sp:MustSupportIssuedTokens />
            <sp:RequireClientEntropy />
            <sp:RequireServerEntropy />
          </wsp:Policy>
        </sp:Trust10>
        <wsaw:UsingAddressing />
      </wsp:All>
    </wsp:ExactlyOne>
  </wsp:Policy>
  <wsp:Policy wsu:Id="WSHttpBinding_IService_GetSimpleType_Input_policy">
    <wsp:ExactlyOne>
      <wsp:All>
        <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
          <sp:Body />
          <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" />
        </sp:SignedParts>
        <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
          <sp:Body />
        </sp:EncryptedParts>
      </wsp:All>
    </wsp:ExactlyOne>
  </wsp:Policy>
  <wsp:Policy wsu:Id="WSHttpBinding_IService_GetSimpleType_output_policy">
    <wsp:ExactlyOne>
      <wsp:All>
        <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
          <sp:Body />
          <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" />
        </sp:SignedParts>
        <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
          <sp:Body />
        </sp:EncryptedParts>
      </wsp:All>
    </wsp:ExactlyOne>
  </wsp:Policy>
  <wsp:Policy wsu:Id="WSHttpBinding_IService_GetCashFlowData_Input_policy">
    <wsp:ExactlyOne>
      <wsp:All>
        <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
          <sp:Body />
          <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" />
        </sp:SignedParts>
        <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
          <sp:Body />
        </sp:EncryptedParts>
      </wsp:All>
    </wsp:ExactlyOne>
  </wsp:Policy>
  <wsp:Policy wsu:Id="WSHttpBinding_IService_GetCashFlowData_output_policy">
    <wsp:ExactlyOne>
      <wsp:All>
        <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
          <sp:Body />
          <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" />
          <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" />
        </sp:SignedParts>
        <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
          <sp:Body />
        </sp:EncryptedParts>
      </wsp:All>
    </wsp:ExactlyOne>
  </wsp:Policy>
  <wsdl:types>
    <xsd:schema targetNamespace="http://tempuri.org/Imports">
      <xsd:import schemaLocation="http://mrecserver.nj.win.com//PIData/Service.svc?xsd=xsd0" namespace="http://tempuri.org/" />
      <xsd:import schemaLocation="http://mrecserver.nj.win.com//PIData/Service.svc?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/" />
      <xsd:import schemaLocation="http://mrecserver.nj.win.com//PIData/Service.svc?xsd=xsd2" namespace="http://schemas.datacontract.org/2004/07/" />
    </xsd:schema>
  </wsdl:types>
  <wsdl:message name="IService_GetSimpleType_InputMessage">
    <wsdl:part name="parameters" element="tns:GetSimpleType" />
  </wsdl:message>
  <wsdl:message name="IService_GetSimpleType_OutputMessage">
    <wsdl:part name="parameters" element="tns:GetSimpleTypeResponse" />
  </wsdl:message>
  <wsdl:message name="IService_GetCashFlowData_InputMessage">
    <wsdl:part name="parameters" element="tns:GetCashFlowData" />
  </wsdl:message>
  <wsdl:message name="IService_GetCashFlowData_OutputMessage">
    <wsdl:part name="parameters" element="tns:GetCashFlowDataResponse" />
  </wsdl:message>
  <wsdl:portType name="IService">
    <wsdl:operation name="GetSimpleType">
      <wsdl:input wsaw:Action="http://tempuri.org/IService/GetSimpleType" message="tns:IService_GetSimpleType_InputMessage" />
      <wsdl:output wsaw:Action="http://tempuri.org/IService/GetSimpleTypeResponse" message="tns:IService_GetSimpleType_OutputMessage" />
    </wsdl:operation>
    <wsdl:operation name="GetCashFlowData">
      <wsdl:input wsaw:Action="http://tempuri.org/IService/GetCashFlowData" message="tns:IService_GetCashFlowData_InputMessage" />
      <wsdl:output wsaw:Action="http://tempuri.org/IService/GetCashFlowDataResponse" message="tns:IService_GetCashFlowData_OutputMessage" />
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="WSHttpBinding_IService" type="tns:IService">
    <wsp:PolicyReference URI="#WSHttpBinding_IService_policy" />
    <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="GetSimpleType">
      <soap12:operation soapAction="http://tempuri.org/IService/GetSimpleType" style="document" />
      <wsdl:input>
        <wsp:PolicyReference URI="#WSHttpBinding_IService_GetSimpleType_Input_policy" />
        <soap12:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <wsp:PolicyReference URI="#WSHttpBinding_IService_GetSimpleType_output_policy" />
        <soap12:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="GetCashFlowData">
      <soap12:operation soapAction="http://tempuri.org/IService/GetCashFlowData" style="document" />
      <wsdl:input>
        <wsp:PolicyReference URI="#WSHttpBinding_IService_GetCashFlowData_Input_policy" />
        <soap12:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <wsp:PolicyReference URI="#WSHttpBinding_IService_GetCashFlowData_output_policy" />
        <soap12:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="Service">
    <wsdl:port name="WSHttpBinding_IService" binding="tns:WSHttpBinding_IService">
      <soap12:address location="http://mrecserver.nj.win.com//PIData/Service.svc" />
      <wsa10:EndpointReference>
        <wsa10:Address>http://mrecserver.nj.win.com//PIData/Service.svc</wsa10:Address>
        <Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
          <Dns>localhost</Dns>
        </Identity>
      </wsa10:EndpointReference>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

..and the following code to return a compiled assembly to use to save the methods.

/// <summary>
/// Compiles an assembly from the proxy class provided by the ServiceDescriptionImporter.
/// </summary>
/// <param name="descriptionImporter"></param>
/// <returns>An assembly that can be used to execute the web service methods.</returns>
private Assembly CompileAssembly(ServiceDescriptionImporter descriptionImporter)
{
    // a namespace and compile unit are needed by importer
    CodeNamespace codeNamespace = new CodeNamespace();
    CodeCompileUnit codeUnit = new CodeCompileUnit();

    codeUnit.Namespaces.Add(codeNamespace);

    ServiceDescriptionImportWarnings importWarnings = descriptionImporter.Import(codeNamespace, codeUnit);

    if (importWarnings == 0) // no warnings
    {
        // create a c# compiler
        CodeDomProvider compiler = CodeDomProvider.CreateProvider("CSharp");

        // include the assembly references needed to compile
        string[] references = new string[2] { "System.Web.Services.dll", "System.Xml.dll" };

        CompilerParameters parameters = new CompilerParameters(references);

        // compile into assembly
        CompilerResults results = compiler.CompileAssemblyFromDom(parameters, codeUnit);

        foreach (CompilerError oops in results.Errors)
        {
            // trap these errors and make them available to exception object
            throw new Exception("Compilation Error Creating Assembly");
        }

        // all done....
        return results.CompiledAssembly;
    }
    else
    {
        // warnings issued from importers, something wrong with WSDL
        throw new Exception("Invalid WSDL");
    }
}

The wsdl passed always go to else part and throw an exception "Invalid WSDL". I noticed that the same piece of code works for those wsdl that doesn't have any linked xsd (i.e. xsd0, xsd1 or xsd2). Can anyone think what could be the problem? and, why does some wcf services have linked xsds and some don't?

Here I am trying to read the wsdl to get all the methods and the properties. I know we can do this easily by adding service reference but I want to do this dynammically as user will pass the service url and I will generate the list of methods with properties.


回答1:


The cause of the problem is that the ServiceDescriptionImporter that is used to generate proxies for the old Xml Web Services (ASMX) assumed it is given a "flattened" wsdl document. That means all the service description documents are in a single wsdl document. You'll need to add a behavior to the WCF service you're targeting to generate the flatten wsdl for your code to work. There are several article on how to generate flattened wsdl but this one should get you started.

EDIT(to summerize comments chat): If you don't have control over the WCF service and still want to use this technique for dynamically generating proxies then you'll need to write code that parses the wsdl to replace the xsd:import elements with the XSD documents pointed to by the url in the import element. The HttpWebRequest .NET Framework class can be used to get the wsdl from a service by calling the service metadata endpoint as if it were a "web page".

Parse the wsdl using your favorite XML class (either XmlDocument or XDocument) to find the import elements and callout for the XSD "web pages" with value in the schemaLocation attribute. You shouldn't need to make any changes in the XSD XML except to remove the XML directive that will be included in the "page" contents. Finally, feed the flattened wsdl to the ServiceDescriptionImporter.



来源:https://stackoverflow.com/questions/5492394/wsdl-with-linked-xsds-are-not-compiled-dynamically-using-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!