您的位置:首页 > 其它

.NET 动态调用WebService + WSE + UsernameToken

2011-04-21 16:26 357 查看
通过几个小时的尝试,终于成功实现动态调用WebService并加入WSE身份验证信息的功能。代码如下:

/// <summary>
/// 动态调用WebService
/// </summary>
private void DynamicInvokeWebService()
{
//1. 创建WebClient下载WSDL信息
WebClient web = new WebClient() ;
Stream stream = web.OpenRead("http://localhost/Service.asmx?wsdl") ;

// 2. 创建和格式化 WSDL 文档。
ServiceDescription description = ServiceDescription.Read(stream);

// 3. 创建客户端代理代理类。
ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
importer.ProtocolName = "Soap"; // 指定访问协议。
importer.Style = ServiceDescriptionImportStyle.Client; // 生成客户端代理。

importer.AddServiceDescription(description, null, null); // 添加 WSDL 文档。

// 4. 使用 CodeDom 编译客户端代理类。
CodeNamespace nmspace = new CodeNamespace(); // 为代理类添加命名空间,缺省为全局空间。
CodeCompileUnit unit = new CodeCompileUnit();
unit.Namespaces.Add(nmspace);

ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit);

//5. 修改WebService接口的基类(默认基类是SoapHttpClientProtocol),而因为使用的wse2.0,所以需要修改基类以便后面传递身份验证信息
CodeTypeDeclaration ctDecl = nmspace.Types[0];
nmspace.Types.Remove(ctDecl);
ctDecl.BaseTypes[0] = new CodeTypeReference("Microsoft.Web.Services2.WebServicesClientProtocol");
nmspace.Types.Add(ctDecl);

//创建代码生成器
CodeDomProvider provider = new Microsoft.CSharp.CSharpCodeProvider() ;

//6. 指定代码生成器,并获得源码
ICodeGenerator icg = provider.CreateGenerator();
StringBuilder srcStringBuilder = new StringBuilder();
StringWriter sw = new StringWriter(srcStringBuilder);
icg.GenerateCodeFromNamespace(nmspace, sw, null);
string proxySource = srcStringBuilder.ToString();
sw.Close();

//7. 创建编译的参数
CompilerParameters parameter = new CompilerParameters();
//注意以下两个属性设置为false才能在多次动态调用时不会报错
parameter.GenerateExecutable = false;
parameter.GenerateInMemory = false;
//用于输出dll文件,调试的时候查看结果
//parameter.OutputAssembly = "WebService.dll"; // 可以指定你所需的任何文件名。
parameter.ReferencedAssemblies.Add("System.dll");
parameter.ReferencedAssemblies.Add("System.XML.dll");
parameter.ReferencedAssemblies.Add("System.Web.Services.dll");
parameter.ReferencedAssemblies.Add("System.Data.dll");
parameter.ReferencedAssemblies.Add("Microsoft.Web.Services.dll");
parameter.ReferencedAssemblies.Add("Microsoft.Web.Services2.dll");

//8. 动态编译文件
ICodeCompiler compiler = provider.CreateCompiler();
CompilerResults result = compiler.CompileAssemblyFromSource(parameter,proxySource) ;//compiler.CompileAssemblyFromDom(parameter, unit);

try
{
// 9. 检查编译是否出错
if (!result.Errors.HasErrors)
{
//10. 使用 Reflection 调用 WebService。
Assembly asm = result.CompiledAssembly;
Type t = asm.GetType("Service"); // 如果在前面为代理类添加了命名空间,此处需要将命名空间添加到类型前面。

object o = Activator.CreateInstance(t)  ;
Microsoft.Web.Services2.WebServicesClientProtocol service = o as Microsoft.Web.Services2.WebServicesClientProtocol ;
//创建用户名安全令牌
Microsoft.Web.Services2.Security.Tokens.UsernameToken token =
new Microsoft.Web.Services2.Security.Tokens.UsernameToken(txtUserName.Text,txtPassword.Text,Microsoft.Web.Services2.Security.Tokens.PasswordOption.SendPlainText) ;
//在安全凭证中添加安全令牌
service.RequestSoapContext.Security.Tokens.Add(token) ;
//调用WebService的方法
MethodInfo method = t.GetMethod("AddData");
//传递方法所需参数
string returnString = (string)method.Invoke(o,new object[]{"参数1","参数2"}) ;
//获取返回结果
this.txtResult.Text = returnString ;
}
else
{
this.txtResult.Text = "编译出错";
}
}
catch(Exception ex)
{
this.txtResult.Text = ex.Message ;
}

}
如果需要更深的了解,可以参考DynWSLib的 源码(第三方开源,可惜官方网站在却无法下载),提供老版下载地址:http://files.cnblogs.com/HarrisonYu/DynWSLib.rar
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: