終於搞定“動態調用WebService方法”:
我在學習 動態調用WebService方法時看到很多網友在調用函數(其實往往是“無參”函數)時得到一個錯誤:
未將對象引用設置到對象的實例。
這個錯誤很常見,貌似不好處理,沒明白的人不知所云,所以這裏提醒我們自己:凡是都要有信心。
導致大家以爲動態調用沒有成功,對整個動態調用方法都失去的信心,其實不然。
我研究了 MethodInfo的這個方法Invoke,發現通過拼湊方法可以變相成功。
爲了方便學習的人,把所涉及到的內容都提上來。第一次寫博客,我也是參考了N多網友的成功經驗,一併謝謝了。
請大家注意下面這句:
//我就是添加了下面的語句,就算是完全解決了調用WebService中函數帶參和不帶參的方法,雖然我對一些理論不是很清楚,但是用拼湊的方法調試,到是成功了。
WebServiceHelper.cs
using System.Net;
using System.CodeDom;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Views.Base;
using System.Data.Common;
using CrystalDecisions.Shared;
using CrystalDecisions.CrystalReports.Engine;
using System.IO;
using System.Drawing.Printing;
using System.Drawing.Imaging;
using Microsoft.Reporting.WinForms;
using System.Configuration;
using System.Web.Services;
using System.Web.Services.Description;
using Microsoft.CSharp;
using System.Reflection;
using System.CodeDom.Compiler;
namespace Print_ACCS
{
public static class WebServiceHelper
{
//動態調用web服務
public static object InvokeWebService(string url, string methodname, object[] args)
{
return WebServiceHelper.InvokeWebService(url, null, methodname, args);
}
public static object InvokeWebService(string url, string classname, string methodname, object[] args)
{
string @namespace = "EnterpriseServerBase.WebService.DynamicWebCalling";
if ((classname == null) || (classname == ""))
{
classname = WebServiceHelper.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);//我就是添加了下面的語句,就算是完全解決了調用WebService中函數帶參和不帶參的方法,雖然我對一些理論不是很清楚,但是用拼湊的方法調試總是解決了,還是早點把這個程序弄完吧。
if (args[0] != "")
return mi.Invoke(obj, args);
else
//Invoke(obj, BindingFlags.Default, new MyBinder(), new Object[] { (int)32, (int)32 }, CultureInfo.CurrentCulture);//這個是msdn上的,比較複雜有時間再琢磨。
return mi.Invoke(obj, BindingFlags.Default, null, null, null);
}
catch (Exception ex)
{
throw new Exception(ex.InnerException.Message, new Exception(ex.InnerException.StackTrace));
}
}
private static string GetWsClassName(string wsUrl)
{
string[] parts = wsUrl.Split('/');
string[] pps = parts[parts.Length - 1].Split('.');
return pps[0];
}
}
}
在主程序中增加:
public static string WebSer_url = ConfigurationSettings.AppSettings["WebService_url"];
在配置文件app.config中:增加WebService_url
<?xml version="1.0"?>
<configuration>
<configSections>
</configSections>
<appSettings>
<add key="WebService_url" value="http://192.168.3.117/ws/Service.asmx" />
</appSettings>
</configuration>
WebService的代碼:
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Data;
using System.Configuration;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.OracleClient;
using System.Text;
namespace handsome
{
[WebService(Namespace = "http://www.xxxx.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
//若要允許使用 ASP.NET AJAX 從腳本中調用此 Web 服務,請取消對下行的註釋。
// [System.Web.Script.Services.ScriptService]
public class Service : System.Web.Services.WebService
{
public Service()
{
//如果使用設計的組件,請取消註釋以下行
//InitializeComponent();
}
private void InitializeComponent()
{
}
[WebMethod]
public string HelloWorld1()
{
myheader.isValid(out msg);
return "Hello World1";
}
[SoapHeader("myheader")]
[WebMethod]
public string HelloWorld2()
{
return "Hello World2";
}
[WebMethod(Description = "返回銷售發票的條碼")]
public string getbarcode_byINV_NO(string str_no)
{
return DbUtil_XSFP.getbarcode_byINV_NO(str_no);
}
}
}
具體調用時:
string st="";//爲默認空變量,或者具體數值
File.WriteAllText(reportPath + file_barcode, (string)WebServiceHelper.InvokeWebService(logfrm.WebSer_url, "getbarcode_byINV_NO", new string[] { st }), Encoding.Default);
或者:
dev_gridcontr.DataSource = (DataTable)WebServiceHelper.InvokeWebService(logfrm.WebSer_url, "Get_XSFP_TIME", new string[] { "" });
或
object result = WebServiceHelper.InvokeWebService(url, "getbarcode_byINV_NO", new string[] { "CZXSFP-1202000088" });
前端代碼參考:
http://files.cnblogs.com/handsome1234/DynamicCallWebservice_Demo.rar