' Main SOAP method Public Function SOAP() As Boolean Dim lcName As String = "" Dim lcValue As String = "" Dim loObject(2) As Object Dim loBasicHttpBinding As System.ServiceModel.BasicHttpBinding = New System.ServiceModel.BasicHttpBinding() Dim loEndpointAddress As System.ServiceModel.EndpointAddress = Nothing Dim loHttpRequestMessageProperty As System.ServiceModel.Channels.HttpRequestMessageProperty = New System.ServiceModel.Channels.HttpRequestMessageProperty() Dim loOperationContextScope As OperationContextScope = Nothing Dim loServiceSVC As ServiceSVC.ClaimServiceSoapClient = Nothing ' Reset the values cMessage = "" cSOAPMessage = "" cXMLReceived = "" ' Set the URL loEndpointAddress = New System.ServiceModel.EndpointAddress(cUrl) ' Set the mode Select Case nBasicHttpSecurityMode ' HTTPS Case 1 loBasicHttpBinding.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.Transport End Select ' Bind the mode and the URL loServiceSVC = New ServiceSVC.ClaimServiceSoapClient(loBasicHttpBinding, loEndpointAddress) ' Add the hook to intercept the envelope loServiceSVC.Endpoint.Behaviors.Add(New CustomBehavior(Me)) ' If we have at least one HTTP header If oHTTPHeader.Count > 0 Then loOperationContextScope = New OperationContextScope(loServiceSVC.InnerChannel) ' For each header For Each loObject In oHTTPHeader ' Initialization lcName = loObject(1) lcValue = loObject(2) ' Add the header loHttpRequestMessageProperty.Headers(lcName) = lcValue Next ' Set the header OperationContext.Current.OutgoingMessageProperties(System.ServiceModel.Channels.HttpRequestMessageProperty.Name) = _ loHttpRequestMessageProperty End If Try ' Invoke the method cXMLReceived = loServiceSVC.SaveClaim(cXMLToSend) Dim loInvoker As New WebServiceInvoker(oApp, New Uri(cUrl)) Dim loArgs As String() = New String() {cXMLToSend} 'cXMLReceived = loInvoker.InvokeMethod(Of String)("ServiceSVC", cMethod, loArgs) lSuccess = True Catch loError As Exception cMessage = loError.Message End Try ' Reset the values cXMLToSend = "" oHTTPHeader.Clear() oMessageHeader.Clear() Return lSuccess End FunctionAs you can see, the commented line for loInvoker.InvokeMethod() is where I would like to adjust so to work with the loServiceSVC object instead of the Service name. The WebService invoker class, as shown below, works with the Service name. But, in that case, I need to work with the loServiceSVC object as this object contains a binding, a different transport mode and a custom behavior so I can intercept the in and out of the transaction.
Public Class WebServiceInvoker Private availableTypes As Dictionary(Of String, Type) Private oApp As Framework.App = Nothing ''' <summary> ''' Text description of the available services within this web service. ''' </summary> Public ReadOnly Property AvailableServices() As List(Of String) Get Return Me.services End Get End Property ''' <summary> ''' Creates the service invoker using the specified web service. ''' </summary> ''' <param name="webServiceUri"></param> Public Sub New(ByVal toApplication As Framework.App, webServiceUri As Uri) oApp = toApplication Me.services = New List(Of String)() ' available services Me.availableTypes = New Dictionary(Of String, Type)() ' available types ' create an assembly from the web service description Me.webServiceAssembly = BuildAssemblyFromWSDL(webServiceUri) ' see what service types are available Dim types As Type() = Me.webServiceAssembly.GetExportedTypes() ' and save them For Each type As Type In types services.Add(type.FullName) availableTypes.Add(type.FullName, type) Next End Sub ''' <summary> ''' Gets a list of all methods available for the specified service. ''' </summary> ''' <param name="serviceName"></param> ''' <returns></returns> Public Function EnumerateServiceMethods(serviceName As String) As List(Of String) Dim methods As New List(Of String)() If Not Me.availableTypes.ContainsKey(serviceName) Then Throw New Exception("Service Not Available") Else Dim type As Type = Me.availableTypes(serviceName) ' only find methods of this object type (the one we generated) ' we don't want inherited members (this type inherited from SoapHttpClientProtocol) For Each minfo As MethodInfo In type.GetMethods(BindingFlags.Instance Or BindingFlags.[Public] Or BindingFlags.DeclaredOnly) methods.Add(minfo.Name) Next Return methods End If End Function ''' <summary> ''' Invokes the specified method of the named service. ''' </summary> ''' <typeparam name="T">The expected return type.</typeparam> ''' <param name="serviceName">The name of the service to use.</param> ''' <param name="methodName">The name of the method to call.</param> ''' <param name="args">The arguments to the method.</param> ''' <returns>The return value from the web service method.</returns> Public Function InvokeMethod(Of T)(serviceName As String, methodName As String, ParamArray args As Object()) As T ' create an instance of the specified service ' and invoke the method Dim obj As Object = Me.webServiceAssembly.CreateInstance(serviceName) Dim type As Type = obj.[GetType]() Return DirectCast(type.InvokeMember(methodName, BindingFlags.InvokeMethod, Nothing, obj, args), T) End Function ''' <summary> ''' Builds the web service description importer, which allows us to generate a proxy class based on the ''' content of the WSDL described by the XmlTextReader. ''' </summary> ''' <param name="xmlreader">The WSDL content, described by XML.</param> ''' <returns>A ServiceDescriptionImporter that can be used to create a proxy class.</returns> Private Function BuildServiceDescriptionImporter(xmlreader As XmlTextReader) As ServiceDescriptionImporter ' make sure xml describes a valid wsdl If Not ServiceDescription.CanRead(xmlreader) Then Throw New Exception("Invalid Web Service Description") End If ' parse wsdl Dim serviceDescription__1 As ServiceDescription = ServiceDescription.Read(xmlreader) ' build an importer, that assumes the SOAP protocol, client binding, and generates properties Dim descriptionImporter As New ServiceDescriptionImporter() descriptionImporter.ProtocolName = "Soap" descriptionImporter.AddServiceDescription(serviceDescription__1, Nothing, Nothing) descriptionImporter.Style = ServiceDescriptionImportStyle.Client descriptionImporter.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties Return descriptionImporter End Function ''' <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 Function CompileAssembly(descriptionImporter As ServiceDescriptionImporter) As Assembly ' a namespace and compile unit are needed by importer Dim codeNamespace As New CodeNamespace() Dim codeUnit As New CodeCompileUnit() codeUnit.Namespaces.Add(codeNamespace) Dim importWarnings As ServiceDescriptionImportWarnings = descriptionImporter.Import(codeNamespace, codeUnit) If importWarnings = 0 Then ' no warnings ' create a c# compiler Dim compiler As CodeDomProvider = CodeDomProvider.CreateProvider("CSharp") ' include the assembly references needed to compile Dim references As String() = New String(1) {"System.Web.Services.dll", "System.Xml.dll"} Dim parameters As New CompilerParameters(references) ' compile into assembly Dim results As CompilerResults = compiler.CompileAssemblyFromDom(parameters, codeUnit) For Each oops As CompilerError In results.Errors ' trap these errors and make them available to exception object Throw New Exception("Compilation Error Creating Assembly") Next ' all done.... Return results.CompiledAssembly Else ' warnings issued from importers, something wrong with WSDL Throw New Exception("Invalid WSDL") End If End Function ''' <summary> ''' Builds an assembly from a web service description. ''' The assembly can be used to execute the web service methods. ''' </summary> ''' <param name="webServiceUri">Location of WSDL.</param> ''' <returns>A web service assembly.</returns> Private Function BuildAssemblyFromWSDL(webServiceUri As Uri) As Assembly If [String].IsNullOrEmpty(webServiceUri.ToString()) Then Throw New Exception("Web Service Not Found") End If Dim xmlreader As New XmlTextReader(webServiceUri.ToString() + "?wsdl") Dim descriptionImporter As ServiceDescriptionImporter = BuildServiceDescriptionImporter(xmlreader) Return CompileAssembly(descriptionImporter) End Function Private webServiceAssembly As Assembly Private services As List(Of String) End ClassAnyone would know if it would be possible to have the main class method to be adjusted so it would support a dynamic method call? By that, I would be able to have this class to be generic for any Service reference I would have to negotiate with and would be able to add a class cMethod property to indicate which method I would like to execute.