Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Using a Service reference dynamically
Message
De
12/09/2012 11:10:20
 
 
À
Tous
Information générale
Forum:
ASP.NET
Catégorie:
Web Services
Titre:
Using a Service reference dynamically
Versions des environnements
Environment:
VB 9.0
OS:
Windows 7
Network:
Windows 2003 Server
Database:
MS SQL Server
Application:
Web
Divers
Thread ID:
01552778
Message ID:
01552778
Vues:
64
I have the following class main method to send a request from a Service reference to a Web Service:
        ' 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 Function
As 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.

The WebService invoker is as follow:
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 Class
Anyone 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.
Michel Fournier
Level Extreme Inc.
Designer, architect, owner of the Level Extreme Platform
Subscribe to the site at https://www.levelextreme.com/Home/DataEntry?Activator=55&NoStore=303
Subscription benefits https://www.levelextreme.com/Home/ViewPage?Activator=7&ID=52
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform