简体   繁体   English

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

[英]Dynamically invoke WCF Service from its URI (http://ip:port/Service1.svc?WSDL)

So here it is: 所以这里是:

I am trying to invoke a WCF Service's method from with in a windows form client application. 我试图在Windows窗体客户端应用程序中调用WCF服务的方法。 I do not have the Contract Class Definition. 我没有合同类定义。 The only thing I have is the Service's URI, which is http://ip:port/Service1.svc . 我唯一拥有的是服务的URI,它是http:// ip:port / Service1.svc

So I thought i could make a proxy class for that. 所以我想我可以为此制作一个代理类。 I want to make the proxy class at run time so any external tool to create a proxy class and import to project can't help me. 我想在运行时创建代理类,所以任何创建代理类和导入到项目的外部工具都无法帮助我。

I managed to make the proxy class on the fly. 我设法动态地制作代理类。 Here's the code: 这是代码:

        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) 

Now using the results I make an Instance of my WebService ( methodName = "GetData" , args = new Object() { 4 } ): See Below.. 现在使用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)

The last command throws an Exception 最后一个命令抛出异常

    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)

Below You can find the web.config of the Web Service and the App.config of the client application 下面您可以找到Web服务的web.config和客户端应用程序的App.config

web.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 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>

Additionally I am sending the contract and the code class of the WebService 另外,我发送合同和WebService的代码类

Contract 合同

    <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

Code 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

Does any one knows the solution? 有人知道解决方案吗? What is the proper way to invoke a WCF method Dynamically if someone only knows the URI? 如果有人只知道URI,那么动态调用WCF方法的正确方法是什么? PS: the Web Service is Up and Running on an IIS7 PS:Web服务已启动并在IIS7上运行

So guys the above procedure works. 所以大家上面的程序是有效的。 It makes an assemply on the fly and then uses that to run methods. 它可以在运行中进行组合,然后使用它来运行方法。 The think is now that I want to call a CompositeType from the assemply, but this is a different scenario. 现在的想法是我想从assemply中调用CompositeType,但这是一个不同的场景。 For primitive types of parameters/return values, for BasicHttpBinding and WCF Web Services, the above works. 对于基本类型的参数/返回值,对于BasicHttpBinding和WCF Web服务,以上工作原理。 (The problem was that I had an error in my web.config file, that i didn't copy on the post) (问题是我的web.config文件中有错误,我没有在帖子上复制)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 WCF-在http://xxxxx.xxxx/Service1.svc上没有侦听端点 - WCF - There was no endpoint listening at http://xxxxx.xxxx/Service1.svc 没有端点侦听 http://localhost/Service1.svc - There was no EndPoint listening at http://localhost/Service1.svc WCF SOAP 服务出现错误接收到 HTTP 对 Z80791B3AE7002CB88C246/FAA7 服务的响应时发生错误 - WCF SOAP service give an error An error occurred while receiving the HTTP response to http://localhost/Service1.svc 将service1.svc文件重命名为someNameService.svc后,wcf服务将不会运行 - After renaming the service1.svc file to someNameService.svc wcf service wont run 从REST WCF服务中删除.svc,同时仍启用“?wsdl”和“ / help” - Remove .svc from REST WCF service with “?wsdl” and “/help” still enabled WCF服务相对uri没有.svc - WCF service relative uri without .svc 访问iis中托管的wcf服务可在localhost中运行,但如果通过ip:port / service.svc访问则无法运行 - Accesing wcf service hosted in iis works in localhost but not if accessed by ip:port/service.svc 如何使用现有的wsdl动态调用WCF服务? - How to dynamically invoke WCF service using existing wsdl? wcf服务@ iis-svc可达但wsdl链接不起作用 - wcf service @ iis - svc reachable but wsdl link not working 在https:// wserver:442 / service1.svc上没有侦听端点 - there was no endpoint listening at https://wserver:442/service1.svc
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM