Dynamically access .Net web service using .NET Compile Unit classes
Having a web service that published is very handy way to integrate one system with another. As number of available web service increased, sometime we would need a handy tool also that allow us to dynamically call web service within our code. This blog will discuss how we can do that using .NET 2.0 basic classes
Few weeks back, my team received a requirement to automatically send email to specific person to remind them if an equipment inspection record will be expired, this request actually wasn’t first request we have received, there were more request with same approach to send email or do something based on specific event. What we normally do to complete this is by creating a single service that run periodically to perform the task, however, as number of request increased and when I do server audit I found lots of tiny service like this running on our server. So we decide we gonna have a single service program that will run every hour and this service program will read XML file that will lists web service information need to be invoked.
To complete above scenario we would need a generic wrapper that able to read web service, reflect them and run it as required. Luckily .NET provide base classed called System.Web.Services.Description and System.Reflection.CompileUnit that we can utilize for this
So based on that classed we build another class that we called as WebServiceInvoker, it only contains one function called Invoke to invoke specific web service.
Connect to Web Service
'-- connect to web service and load service description
If Not Credential Is Nothing Then client.Credentials = Credential
Dim stream As Stream = client.OpenRead(String.Format("{0}?wsdl", Url))
Dim description As ServiceDescription = ServiceDescription.Read(stream)
'-- initialize service description importer
Dim importer As ServiceDescriptionImporter = New ServiceDescriptionImporter()
importer.ProtocolName = "Soap12"
importer.AddServiceDescription(description, Nothing, Nothing)
importer.Style = ServiceDescriptionImportStyle.Client
importer.CodeGenerationOptions = Xml.Serialization.CodeGenerationOptions.GenerateProperties
Above code snippet used to read Wsdl entry of webservice going to be invoked. ServiceDescription class will read that entry and with help from ServiceDescriptionImporter class to store information that being read.
Prepare compile unit and compile ws-code into assembly
Dim warning As ServiceDescriptionImportWarnings = importer.Import(nmspace, compileUnit)
If warning = 0 Then
Dim provider As CodeDom.Compiler.CodeDomProvider = CodeDom.Compiler.CodeDomProvider.CreateProvider("VB")
Dim assyRefs() As String = {"System.dll", "System.Web.Services.dll", "System.Web.dll", "System.Xml.dll", "System.Data.dll"}
Dim parms As New CodeDom.Compiler.CompilerParameters(assyRefs)
Dim results As CodeDom.Compiler.CompilerResults = provider.CompileAssemblyFromDom(parms, compileUnit)
In this section we will prepare CodeDomProvider class, attach reference and compile all code unit that already sync into DOM information.
Run the web-service compile result
'-- no error, execute then
Dim wsClass As Object = results.CompiledAssembly.CreateInstance(ServiceName)
If Not Credential Is Nothing Then wsClass.Credentials = Credential
Dim mi As MethodInfo = wsClass.GetType().GetMethod(MethodName)
ret = mi.Invoke(wsClass, args)
Final step is to run the webservice
Full code of WebServiceInvoker will be as follow:
1: Imports System.Net
2: Imports System.IO
3: Imports System.Web.Services
4: Imports System.Web.Services.Description
5: Imports System.Reflection
6:
7: Public Class WebServiceInvoker
8:
9: Public Function Invoke(ByVal Url As String, _
10: ByVal ServiceName As String, ByVal MethodName As String, _
11: ByVal Credential As ICredentials, ByVal args() As Object) As Object
12: Dim ret As Object = Nothing
13:
14: Dim client As New WebClient
15:
16: '-- connect to web service and load service description
17: If Not Credential Is Nothing Then client.Credentials = Credential
18: Dim stream As Stream = client.OpenRead(String.Format("{0}?wsdl", Url))
19: Dim description As ServiceDescription = ServiceDescription.Read(stream)
20:
21: '-- initialize service description importer
22: Dim importer As ServiceDescriptionImporter = New ServiceDescriptionImporter()
23: importer.ProtocolName = "Soap12"
24: importer.AddServiceDescription(description, Nothing, Nothing)
25: importer.Style = ServiceDescriptionImportStyle.Client
26: importer.CodeGenerationOptions = Xml.Serialization.CodeGenerationOptions.GenerateProperties
27:
28: '-- prepare DOM and CompileUnit for service we would like to invoke
29: Dim nmspace As New CodeDom.CodeNamespace()
30: Dim compileUnit As New CodeDom.CodeCompileUnit()
31: compileUnit.Namespaces.Add(nmspace)
32:
33: '-- import service from based on DOM Information into CompileUnit
34: Dim warning As ServiceDescriptionImportWarnings = importer.Import(nmspace, compileUnit)
35: If warning = 0 Then
36: Dim provider As CodeDom.Compiler.CodeDomProvider = CodeDom.Compiler.CodeDomProvider.CreateProvider("VB")
37: Dim assyRefs() As String = {"System.dll", "System.Web.Services.dll", "System.Web.dll", "System.Xml.dll", "System.Data.dll"}
38: Dim parms As New CodeDom.Compiler.CompilerParameters(assyRefs)
39: Dim results As CodeDom.Compiler.CompilerResults = provider.CompileAssemblyFromDom(parms, compileUnit)
40:
41: '-- handling error during compilation
42: If results.Errors.Count > 0 Then
43: For Each err As CodeDom.Compiler.CompilerError In results.Errors
44: Next
45: Throw New System.Exception("Compile Error Occured calling webservice. Check Debug ouput window.")
46: End If
47:
48: '-- no error, execute then
49: Dim wsClass As Object = results.CompiledAssembly.CreateInstance(ServiceName)
50: If Not Credential Is Nothing Then wsClass.Credentials = Credential
51: Dim mi As MethodInfo = wsClass.GetType().GetMethod(MethodName)
52: ret = mi.Invoke(wsClass, args)
53: Else
54: ret = Nothing
55: End If
56:
57: Return ret
58: End Function
59:
60: End Class
Related article(s)
If you think this post is interesting, maybe you would consider to subscribe to my feed by click here or keep update with my newest post via email













حركات
منتدى حركات
مركز تحميل حركات
Leave your response!