Introduction
Invoking a Web Service dynamically is not a new topic. I have been using the following method to invoke a web service without a proxy till recently. Later below, you can see a better way of doing this.
Create your SOAP envelope and contents. You will be playing with some string
s for a while.
The Conventional Method
HttpWebRequest oHttpWebRequest = (HttpWebRequest) WebRequest.Create(URL);
oHttpWebRequest.UseDefaultCredentials = true;
oHttpWebRequest.ContentType = "text/xml";
oHttpWebRequest.Method = "POST";
oHttpWebRequest.Accept = "text/xml";
oHttpWebRequest.Headers.Add("SOAPAction:" + SoapAction);
oHttpWebRequest.UserAgent = "Mozilla/4.0+";
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(sSoapMessage);
Stream oSendStream = oHttpWebRequest.GetRequestStream();
oSendStream.Write(bytes, 0, bytes.Length);
oSendStream.Close();
oHttpResponse = (HttpWebResponse) oHttpWebRequest.GetResponse();
Stream oReceiveStream = oHttpResponse.GetResponseStream();
oHttpResponse.Close();
oReadStream.Close();
I have omitted many plumbing statements here as this is intended only to give a basic idea about how difficult this is.
A Different Approach
The next method also technically works the same way, because there is only one way a SOAP request can be made. The only difference is that the new approach wraps the whole string
manipulation inside itself and does all the plumbing work for us. The basic idea is to generate a proxy assembly when you need it as a one time activity.
Uri uri = new Uri(_mUrl);
WebRequest webRequest = WebRequest.Create(uri);
Authenticate(webRequest);
WebResponse webResponse = webRequest.GetResponse();
Stream requestStream = webResponse.GetResponseStream();
ServiceDescription serviceDescription = ServiceDescription.Read(requestStream);
ServiceDescriptionImporter descriptionImporter = new ServiceDescriptionImporter();
descriptionImporter.AddServiceDescription(serviceDescription, String.Empty, String.Empty);
descriptionImporter.ProtocolName = "Soap";
descriptionImporter.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties;
CodeNamespace codeNamespace = new CodeNamespace();
compilerResults = codeProvider.CompileAssemblyFromDom(compilerParameters, codeCompileUnit);
Assembly assembly = compilerResults.CompiledAssembly;
Type type = assembly.GetType(_mTypeName) ?? FindTypeByName(assembly);
_mTargetInstance = assembly.CreateInstance(_mTypeName);
_mMethodInfo = type.GetMethod(
_mMethodName,
BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.IgnoreReturn);
object result = _mMethodInfo.Invoke(_mTargetInstance, parameters);
The advantage in this approach is that you need to execute this whole thing only once when you find the MethodInfo
object as null
(for the first time). The rest of the time, this will behave just like a normal web service invoke using the conventional method.
I know you might be thinking why should you do like this? Why can’t I invoke like the old way? Well, the answer is ‘it depends’. There are some situations where you decide to post a piece of data to a web service whose URL, method and parameters are known only at run-time, probably from a database configuration or a config file. I found this very useful for my application integration project.
Enjoy coding and let me know if you need help with this.