动态调用WebService
通过web service url调用web method,如果web method返回的是.net通用类型,可以不用添加web引用到工程。比如调用的web method返回的是DataTable类型。
// Client Console Application
using System;
using System.Data;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Net;
using System.IO;
using System.Web.Services.Protocols;
using System.Web.Services.Description;
using System.CodeDom;
using System.CodeDom.Compiler;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
string WebUrl = "http://localhost/mywebservice.asmx";
string myFirstName = "123";
string myLastName = "456";
DataTable dt = new DataTable();
try
{
dt = (DataTable)TestWebService.InvokeWebService(WebUrl, "MyWebService", "MyWebService", "GetMyDataTable", CredentialsType.None, true, new Type[] { typeof(string), typeof(string) }, myFirstName, myLastName);
Console.WriteLine(dt.Rows.Count.ToString());
}
catch (Exception)
{
throw;
}
}
}
public enum CredentialsType
{
None,
Windows
}
public class TestWebService
{
private static Dictionary<string, Assembly> assemblyCache = new Dictionary<string, Assembly>();
private static Assembly assembly = null;
/// <summary>
/// Dynamically invoke a web method from web service assembly.
/// </summary>
/// <param name="url">Web Service URL, e.g. http://localhost/MyWebService.asmx </param>
/// <param name="nameSpace">Web Service NameSpace, e.g. MyWebServiceNameSpace</param>
/// <param name="typeName">Web Service TypeName, e.g. MyWebServiceClass</param>
/// <param name="methodName">The name of invoked web method</param>
/// <param name="credentials">The credential of SoapHttpClientProtocol</param>
/// <param name="assemblyFlag">True - Compiler web service proxy assembly, False - Get executing web service assembly</param>
/// <param name="parmsTypes">The type of invoked web method parameters</param>
/// <param name="args">The value of invoked web method parameters</param>
/// <returns></returns>
public static object InvokeWebService(string url, string nameSpace, string typeName, string methodName, CredentialsType credentials, bool assemblyFlag, Type[] parmsTypes, params object[] args)
{
string fullTypeName = nameSpace + "." + typeName;
if (parmsTypes == null)
{
parmsTypes = new Type[0];
}
if (args == null)
{
args = new object[0];
}
if (parmsTypes.Length != args.Length)
{
throw new Exception("The count of method parameters and types are not equal.");
}
try
{
if (assemblyCache.Count == 0 || !assemblyCache.ContainsKey(fullTypeName))
{
if (assemblyFlag)
{
assembly = CompilerWebProxyAssembly(url, nameSpace, credentials);
}
else
{
assembly = Assembly.GetExecutingAssembly();
}
assemblyCache.Add(fullTypeName, assembly);
}
assembly = assemblyCache[fullTypeName];
if (assembly == null)
{
throw new Exception("Unable to get executing assembly.");
}
Type actionType = assembly.GetType(fullTypeName);
if (actionType == null)
{
throw new Exception("Unable to load the type: " + fullTypeName);
}
MethodInfo methodInfo = actionType.GetMethod(methodName, parmsTypes);
if (methodInfo == null)
{
throw new Exception("Unable to load the method: " + methodName);
}
object obj = assembly.CreateInstance(actionType.FullName);
switch (credentials)
{
case CredentialsType.None:
break;
case CredentialsType.Windows:
SoapHttpClientProtocol protocol = (SoapHttpClientProtocol)obj;
protocol.Credentials = CreateWindowsCredentials(url);
break;
default:
break;
}
return methodInfo.Invoke(obj, args);
}
catch (Exception ex)
{
throw new Exception("Invoke web service failed.\n" + ex.Message);
}
}
private static Assembly CompilerWebProxyAssembly(string url, string nameSpace, CredentialsType credentials)
{
try
{
WebClient webClient = CreateWebServiceClient(url, credentials);
Stream stream = webClient.OpenRead(url + "?WSDL");
ServiceDescription description = ServiceDescription.Read(stream);
ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
importer.ProtocolName = "Soap"; // network protocol
importer.Style = ServiceDescriptionImportStyle.Client; // generate client proxy
importer.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties | System.Xml.Serialization.CodeGenerationOptions.GenerateNewAsync;
importer.AddServiceDescription(description, null, null); // add wsdl document
CodeNamespace space = new CodeNamespace(nameSpace); // add namespace for proxy class
CodeCompileUnit unit = new CodeCompileUnit();
unit.Namespaces.Add(space);
ServiceDescriptionImportWarnings warnings = importer.Import(space, unit);
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = false;
parameters.GenerateInMemory = true;
parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("System.XML.dll ");
parameters.ReferencedAssemblies.Add("System.Web.Services.dll ");
parameters.ReferencedAssemblies.Add("System.Data.dll ");
CompilerResults results = provider.CompileAssemblyFromDom(parameters, unit);
if (!results.Errors.HasErrors)
{
return results.CompiledAssembly;
}
else
{
return null;
}
}
catch (Exception ex)
{
throw new Exception("Complie web proxy assembly failed.\n" + ex.Message);
}
}
private static WebClient CreateWebServiceClient(string url, CredentialsType credentials)
{
try
{
WebClient webClient = new WebClient();
// Extension other credentials
switch (credentials)
{
case CredentialsType.None:
break;
case CredentialsType.Windows:
ICredentials windowsCredentials = CreateWindowsCredentials(url);
webClient.Credentials = windowsCredentials;
break;
default:
break;
}
return webClient;
}
catch (Exception ex)
{
throw new Exception("Create web service client failed." + ex.Message);
}
}
private static ICredentials CreateWindowsCredentials(string url)
{
try
{
string domain = "123";
string username = "123";
string password = "123";
NetworkCredential credential = new NetworkCredential(username, password, domain);
CredentialCache cache = new CredentialCache();
cache.Add(new Uri(url), "NTLM", credential);
return cache;
}
catch (Exception ex)
{
throw new Exception("Create windows credentials failed." + ex.Message);
}
}
}
}
// My Web Service
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Data;
namespace MyWebService
{
/// <summary>
/// Summary description for MyWebService
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class MyWebService : System.Web.Services.WebService
{
[WebMethod]
public DataTable GetMyDataTable(string firstName, string lastName)
{
DataTable dt = new DataTable(firstName + lastName);
return dt;
}
}
}