从其URI(http:// ip:port / Service1.svc?WSDL)动态调用WCF服务

时间:2011-09-09 11:29:51

标签: wcf class proxy dynamic invoke

所以这是:

我试图在Windows窗体客户端应用程序中调用WCF服务的方法。我没有合同类定义。我唯一拥有的是服务的URI,即http://ip:port/Service1.svc

所以我想我可以为此制作一个代理类。我想在运行时创建代理类,所以创建代理类和导入到项目的任何外部工具都无法帮助我。

我设法动态制作代理课程。这是代码:

        Dim mexClient As MetadataExchangeClient = New MetadataExchangeClient(New Uri(webServicesWSDLUrl), MetadataExchangeClientMode.HttpGet)
        mexClient.ResolveMetadataReferences = True
        Dim metaDocs As MetadataSet = mexClient.GetMetadata()

        Dim importer As WsdlImporter = New WsdlImporter(metaDocs)
        Dim generator As ServiceContractGenerator = New ServiceContractGenerator()

        Dim dataContractImporter As New Object
        Dim xsdDCImporter As XsdDataContractImporter
        If (Not importer.State.TryGetValue(GetType(XsdDataContractImporter), dataContractImporter)) Then

            Console.WriteLine("Couldn't find the XsdDataContractImporter! Adding custom importer.")
            xsdDCImporter = New XsdDataContractImporter()
            xsdDCImporter.Options = New ImportOptions()
            importer.State.Add(GetType(XsdDataContractImporter), xsdDCImporter)

        Else

            xsdDCImporter = TryCast(dataContractImporter, XsdDataContractImporter)
            If (xsdDCImporter.Options Is Nothing) Then

                Console.WriteLine("There were no ImportOptions on the importer.")
                xsdDCImporter.Options = New ImportOptions()
            End If

        End If

        Dim exts As System.Collections.IEnumerable = importer.WsdlImportExtensions
        Dim newExts As New System.Collections.Generic.List(Of IWsdlImportExtension)
        For Each ext As IWsdlImportExtension In exts
            Console.WriteLine("Default WSDL import extensions: {0}", ext.GetType().Name)
            newExts.Add(ext)
        Next

        Dim polExts As System.Collections.IEnumerable = importer.PolicyImportExtensions
        importer = New WsdlImporter(metaDocs, polExts, newExts)


        Dim Contracts As System.Collections.ObjectModel.Collection(Of ContractDescription) = importer.ImportAllContracts()
        importer.ImportAllEndpoints()
        importer.ImportAllBindings()



        For Each contract As ContractDescription In Contracts
            generator.GenerateServiceContractType(contract)
        Next


        If generator.Errors.Count <> 0 Then
            Throw New Exception("There were errors during code compilation.")
        End If


        Dim nmspace As CodeNamespace = New CodeNamespace()
        Dim unit1 As CodeCompileUnit = New CodeCompileUnit()
        unit1.Namespaces.Add(nmspace)


        Dim CodeDomProvider As System.CodeDom.Compiler.CodeDomProvider = System.CodeDom.Compiler.CodeDomProvider.CreateProvider("VB")

        Dim assemblyReferences() As String
        assemblyReferences = New String() {"System.dll", _
            "System.Web.Services.dll", "System.Web.dll", _
            "System.Xml.dll", "System.Data.dll"}
        Dim parms As CompilerParameters = New CompilerParameters(assemblyReferences)
        parms.GenerateInMemory = True '(Thanks for this line nikolas)

        'CompilerRsults
        results = CodeDomProvider.CompileAssemblyFromDom(parms, generator.TargetCompileUnit) 

现在使用results我创建了一个WebService实例(methodName = "GetData"args = new Object() { 4 }):见下文..

        Dim wsvcClass As Object = results.CompiledAssembly.CreateInstance(serviceName)
        Dim retValue As Object = wsvcClass.GetType().InvokeMember(methodName, BindingFlags.InvokeMethod, Nothing, wsvcClass, args)

最后一个命令抛出异常

    A first chance exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll
System.ServiceModel.EndpointNotFoundException: There was no endpoint listening at http://ip:port/Service1.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details. ---> System.Net.WebException: The remote server returned an error: (404) Not Found.
   at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   --- End of inner exception stack trace ---

Server stack trace: 
   at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Dispatcher.ReA first chance exception of type 'System.NullReferenceException' occurred in ThirdPartyAPIClientApp.exe
questChannelBinder.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at IService1.GetData(Int32 value)
   at Service1Client.GetData(Int32 value)

下面您可以找到Web服务的web.config和客户端应用程序的App.config

  

的web.config

    <?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true" strict="false" explicit="true" targetFramework="4.0" />
  </system.web>

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel.MessageLogging">
        <listeners>
          <add name="messages"
          type="System.Diagnostics.XmlWriterTraceListener"
          initializeData="c:\logs\messages.svclog" />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>

  <system.serviceModel>

    <diagnostics>
      <messageLogging
           logEntireMessage="true"
           logMalformedMessages="false"
           logMessagesAtServiceLevel="true"
           logMessagesAtTransportLevel="false"
           maxMessagesToLog="3000"
           maxSizeOfMessageToLog="2000"/>
    </diagnostics>

    <services>
      <!-- Note: the service name must match the configuration name for the service implementation. -->
      <service name="WcfService1.Service1" behaviorConfiguration="BasicHttpBinding_This" >
        <endpoint address="/Service1.svc" contract="WcfService1.IService1" binding="basicHttpBinding" bindingNamespace="http://ip:port/WCF1_Test" />
        <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
      </service>
    </services>


    <behaviors>
      <serviceBehaviors>
        <behavior name="BasicHttpBinding_This">
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <bindings>


      <basicHttpBinding>

        <binding name="BasicHttpBinding_This" closeTimeout="00:01:00"
          openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
          bypassProxyOnLocal="false"  hostNameComparisonMode="StrongWildcard"
          maxBufferPoolSize="200000000000000" maxReceivedMessageSize="200000000000000"
          messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
          allowCookies="false">
          <readerQuotas maxDepth="32" maxStringContentLength="2147483647"
            maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />

          <security mode="None">
            <transport clientCredentialType="Windows" proxyCredentialType="None"
              realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>

</configuration>
  

的App.config

 <?xml version="1.0"?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
    </startup>

    <system.serviceModel>
        <bindings>
          <basicHttpBinding>
            <binding name="BasicHttpBinding_This" closeTimeout="00:01:00"
              openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
              bypassProxyOnLocal="false"  hostNameComparisonMode="StrongWildcard"
              maxBufferPoolSize="200000000" maxReceivedMessageSize="200000000"
              messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
              allowCookies="false">
              <readerQuotas maxDepth="32" maxStringContentLength="200000000"
                maxArrayLength="200000000" maxBytesPerRead="200000000" maxNameTableCharCount="200000000" />

              <security mode="None">
                <transport clientCredentialType="Windows" proxyCredentialType="None"
                  realm="" />
                <message clientCredentialType="UserName" algorithmSuite="Default" />
              </security>
            </binding>
          </basicHttpBinding>
        </bindings>
        <client>

          <endpoint address="http://ip:port/Service1.svc"
                binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_This"
                contract="IService1" name="BasicHttpBinding_This" />

        </client>
    </system.serviceModel>
</configuration>

此外,我发送合同和WebService的代码类

  

合同

    <ServiceContract(Namespace:="http://ip:port/WCF1_Test")>
    Public Interface IService1

    <OperationContract(isOneway:=False)>
    Function GetData(ByVal value As Integer) As String

    <OperationContract(isOneway:=False)>
    Function GetDataUsingDataContract(ByVal composite As CompositeType) As CompositeType

    ' TODO: Add your service operations here

End Interface

' Use a data contract as illustrated in the sample below to add composite types to service operations.

<DataContract()>
Public Class CompositeType

    <DataMember()>
    Public Property BoolValue() As Boolean

    <DataMember()>
    Public Property StringValue() As String

End Class
  

代码类

    <ServiceBehavior(Namespace:="http://ip:port/WCF1_Test")>
Public Class Service1
    Implements IService1

    Public Sub New()
    End Sub

    Public Function GetData(ByVal value As Integer) As String Implements IService1.GetData
        Return String.Format("You entered: {0}", value)
    End Function

    Public Function GetDataUsingDataContract(ByVal composite As CompositeType) As CompositeType Implements IService1.GetDataUsingDataContract
        If composite Is Nothing Then
            Throw New ArgumentNullException("composite")
        End If
        If composite.BoolValue Then
            composite.StringValue &= "Suffix"
        End If
        Return composite
    End Function

End Class

有人知道解决方案吗?如果有人只知道URI,那么动态调用WCF方法的正确方法是什么?  PS:Web服务已启动并在IIS7上运行

1 个答案:

答案 0 :(得分:0)

所以大家上面的程序有效。它可以在运行中进行组合,然后使用它来运行方法。现在的想法是我想从assemply中调用CompositeType,但这是一个不同的场景。对于基本类型的参数/返回值,对于BasicHttpBinding和WCF Web服务,以上工作原理。 (问题是我的web.config文件中有错误,我没有在帖子上复制)