请教客户端调用webservice的问题

lendylixt 2012-08-16 04:19:12
从网上看到一个动态调用webservice的例子,
http://www.cnblogs.com/uleewang/archive/2009/05/13/1455699.html
自己做了一下尝试

webservice代码如下

using System;
using System.Data;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.ComponentModel;

namespace LenWebService
{
/// <summary>
/// Service1 的摘要说明
/// </summary>
[WebService(Namespace = "http://localhost/LenWebService/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{

[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
[WebMethod]
public int Add2(int a)
{
return a + 2;
}
}
}

客户端代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Net;
using System.Web;
using System.Web.Services;
using System.Web.Services.Description;
using System.Web.Services.Protocols;
using System.Xml.Serialization;

namespace SV
{
public partial class frmCommunity : Form
{
public frmCommunity()
{
InitializeComponent();
}

private void btnChk_Click(object sender, EventArgs e)
{
WebClient client = new WebClient();
string url = this.txtUrl.Text.ToString().Trim();
Stream stream = client.OpenRead(url);
ServiceDescription description = ServiceDescription.Read(stream);

ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
importer.ProtocolName = "Soap";
importer.Style = ServiceDescriptionImportStyle.Client;
importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;
importer.AddServiceDescription(description, null, null);

CodeNamespace nmspace = new CodeNamespace();
nmspace.Name = "LenWebService";
CodeCompileUnit unit = new CodeCompileUnit();
unit.Namespaces.Add(nmspace);

ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit);
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");

CompilerParameters parameter = new CompilerParameters();
parameter.GenerateExecutable = false;
parameter.OutputAssembly = "LenWebClient.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");

CompilerResults result = provider.CompileAssemblyFromDom(parameter, unit);
if (result.Errors.HasErrors)
{
lsLog.Items.Add("有错");
}

Assembly asm = Assembly.LoadFrom("LenWebClient.dll");
Type t = asm.GetType("LenWebService.Service1");

object o = Activator.CreateInstance(t);
MethodInfo HelloWord = t.GetMethod("HelloWorld");

string Result = (string)HelloWord.Invoke(o, null);
lsLog.Items.Add(result);
lsLog.Items.Add("结束");
}

private void frmCommunity_Load(object sender, EventArgs e)
{
this.txtUrl.Text = "http://localhost/lenwebservice/service1.asmx?WSDL";
}
}
}


运行的结果显示:
System.CodeDom.Compiler.CompilerResults
结束

两个问题
1、程序运行结果没达到预想的返回“hollow world”字符串的效果
不知道问题出在什么地方
2、是如何调用另外一个需要输入参数的webmethod
...全文
334 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
lendylixt 2012-08-17
  • 打赏
  • 举报
回复
确实犯了2级错误
改了,可以用,谢谢8楼

5楼的方法也很好,很方便
确实万能


7楼的方法我大概试了一下,还是不成功啊
下面是我写的类

using System;
using System.Collections.Generic;
using System.Text;

namespace SV
{
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(Name = "Service1Soap", Namespace = "http://localhost/LenWebService/")]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(object[]))]
class LenWebClient : System.Web.Services.Protocols.SoapHttpClientProtocol
{
public LenWebClient()
{
this.Url = "http://localhost/lenwebservice/service1.asmx";
}

[System.Web.Services.Protocols.SoapDocumentMethodAttribute(
"http://localhost/LenWebService/Service1",
RequestNamespace = "http://localhost/LenWebService/",
ResponseNamespace = "http://localhost/LenWebService/",
Use = System.Web.Services.Description.SoapBindingUse.Literal,
ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]

public string HellowWorld()
{
object[] results = this.Invoke("HelloWorld", null);
return ((string)(results[0]));
}

public int Add2(int a)
{
object[] results = this.Invoke("Add2", new object[] { a });
return ((int)(results[0]));
}
}
}

调用实例化以后调用方法,报错
未处理ArgumentNullException
值不能为空
  • 打赏
  • 举报
回复
楼主犯了个低级错误:

CompilerResults result = provider.CompileAssemblyFromDom(parameter, unit);

string Result = (string)HelloWord.Invoke(o, null);
lsLog.Items.Add(result);

注意大小写!
zhoucong1020 2012-08-16
  • 打赏
  • 举报
回复
你可以尝试这个类,不用你写的这么复杂,大概看你的改了一下,应该能用

[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.0.30319.1")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(Name = "Service1Soap", Namespace = "http://localhost/LenWebService/")]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(object[]))]
public class SimpleProxy : System.Web.Services.Protocols.SoapHttpClientProtocol
{
public SimpleProxy()
{
this.Url = "http://localhost/lenwebservice/service1.asmx";
}

[System.Web.Services.Protocols.SoapDocumentMethodAttribute(
"http://localhost/LenWebService/Service1",
RequestNamespace = "http://localhost/LenWebService/",
ResponseNamespace = "http://localhost/LenWebService/",
Use = System.Web.Services.Description.SoapBindingUse.Literal,
ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public int Add2(int a)
{
object[] results = this.Invoke("Add2", new object[] { a });
return ((int)(results[0]));
}
}
Devil月哥 2012-08-16
  • 打赏
  • 举报
回复
直接引用网站的WebService的类就好了
rongshuohan1989 2012-08-16
  • 打赏
  • 举报
回复
虽然我不太懂LZ给的那些东西,但是我给你一个我自己在用的,就是2L说的WSDL

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Services;
using System.Net;
using System.IO;
using System.Web.Services.Description;
using System.CodeDom;
using Microsoft.CSharp;
using System.CodeDom.Compiler;

namespace HZZYKJ.RTFWS.WEBSERVICE
{
public class WebServiceForRTS
{
#region InvokeWebService
/// <summary>
/// 动态调用WebService
/// </summary>
/// <param name="url">WebService地址</param>
/// <param name="methodname">方法名(模块名)</param>
/// <param name="args">参数列表,无参数为null</param>
/// <returns>object</returns>
public static object InvokeWebService(string url, string methodname, object[] args)
{
return WebServiceForRTS.InvokeWebService(url, null, methodname, args);
}

public static object InvokeWebService(string url, string methodname)
{
return WebServiceForRTS.InvokeWebService(url, null, methodname, null);
}

/// <summary>
/// 动态调用WebService
/// </summary>
/// <param name="url">WebService地址</param>
/// <param name="classname">类名</param>
/// <param name="methodname">方法名(模块名)</param>
/// <param name="args">参数列表</param>
/// <returns>object</returns>
public static object InvokeWebService(string url, string classname, string methodname, object[] args)
{
string @namespace = "EnterpriseServerBase.WebService.DynamicWebCalling";
if ((classname == null) || (classname == ""))
{
classname = WebServiceForRTS.GetWsClassName(url);
}

try
{
//获取WSDL
WebClient wc = new WebClient();
Stream stream = wc.OpenRead(url + "?WSDL");
ServiceDescription sd = ServiceDescription.Read(stream);
ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
sdi.AddServiceDescription(sd, "", "");
CodeNamespace cn = new CodeNamespace(@namespace);

//生成客户端代理类代码
CodeCompileUnit ccu = new CodeCompileUnit();
ccu.Namespaces.Add(cn);
sdi.Import(cn, ccu);
CSharpCodeProvider csc = new CSharpCodeProvider();
ICodeCompiler icc = csc.CreateCompiler();

//设定编译参数
CompilerParameters cplist = new CompilerParameters();
cplist.GenerateExecutable = false;
cplist.GenerateInMemory = true;
cplist.ReferencedAssemblies.Add("System.dll");
cplist.ReferencedAssemblies.Add("System.XML.dll");
cplist.ReferencedAssemblies.Add("System.Web.Services.dll");
cplist.ReferencedAssemblies.Add("System.Data.dll");

//编译代理类
CompilerResults cr = icc.CompileAssemblyFromDom(cplist, ccu);
if (true == cr.Errors.HasErrors)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (System.CodeDom.Compiler.CompilerError ce in cr.Errors)
{
sb.Append(ce.ToString());
sb.Append(System.Environment.NewLine);
}
throw new Exception(sb.ToString());
}

//生成代理实例,并调用方法
System.Reflection.Assembly assembly = cr.CompiledAssembly;
Type t = assembly.GetType(@namespace + "." + classname, true, true);
object obj = Activator.CreateInstance(t);
System.Reflection.MethodInfo mi = t.GetMethod(methodname);

return mi.Invoke(obj, args);
}
catch (Exception ex)
{
throw new Exception(ex.InnerException.Message, new Exception(ex.InnerException.StackTrace));
}
}

//最终的返回amsx文件名
private static string GetWsClassName(string wsUrl)
{
string[] parts = wsUrl.Split('/');
string[] pps = parts[parts.Length - 1].Split('.');

return pps[0];
}
#endregion
}
}


那个string[]就是要输入的参数,0~n都可以,几乎是万用的客户端调用
lendylixt 2012-08-16
  • 打赏
  • 举报
回复
就是想动态调用webservice
webservice的测试环境和真实环境会有差异
通过配置文件修改地址方便一些
lendylixt 2012-08-16
  • 打赏
  • 举报
回复
就是想试试动态调用的方法
webservice的测试环境和真实环境会略有不同
添加引用的办法不太灵活
zhoucong1020 2012-08-16
  • 打赏
  • 举报
回复
你可以尝试用wsdl工具生成你需要的代码,在vs命令行里执行
wsdl /language:CS /out:D:\TestProxy.cs http://localhost:1368/TestService.asmx
把路径和服务地址替换了就行了,生成出来的类有同步、异步操作,比较方便
wfy4422 2012-08-16
  • 打赏
  • 举报
回复
不用这么复杂的。在客户端项目里添加Web服务引用,会自动封装一个类,客户端调用这个类的方法就行了

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧