今天看了李天平关于WinForm调用Web Service的代码,我自己模仿做一个代码基本都是复制粘贴的,结果不好使。郁闷的是,又碰到那个该死的GET调用Web Service,我想肯定又是Web.config需要配置,结果WinForm没有这个配置文件,奇怪,为什么人家的就好使,我写的就不好使呢。
上网搜吧,唉,找个两个多小时,基本都是和我一样的代码,互相转载。根本没人提代码好不好使,也没人提正确的用法。就在我要放弃的时候,终于发现原来是在 Web Service的Web.config里配置的(下面滴2步),真是欲哭无泪啊,大家可要注意啊。
好了,把过程详细说下吧。
1、建立项目WebService和WinForm项目,这里起名为WinFormInvokeWebService,如图所示
2、Service1.asmx代码为:(这部分其实和上篇的代码是一样的)
using System;
using System.Collections.Generic;
using System.Linq; using System.Web; using System.Web.Services; using System.Data; namespace WebService1 { /// <summary> /// Service1 的摘要说明 /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.ComponentModel.ToolboxItem(false)] // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。 [System.Web.Script.Services.ScriptService] public class Service1 : System.Web.Services.WebService { //无参方法 [WebMethod] public string HelloWorld() { return "Hello World"; } //有参方法1 [WebMethod] public int Add(int a, int b) { return a + b; } //有参方法2 [WebMethod] public int Sum(int x) { int sum = 0; for (int i = 0; i <= x; i++) { sum += i; } return sum; } // 返回一个复合类型 [WebMethod] public Student GetStudentByStuNo(string stuNo) { if(stuNo=="001") return new Student { StuNo = "001", StuName = "张三" }; if(stuNo=="002") return new Student { StuNo = "002", StuName = "李四" }; return null; } //返回返回泛型集合的 [WebMethod] public List<Student> GetList() { List<Student> list = new List<Student>(); list.Add(new Student() { StuNo = "001", StuName = "张三" }); list.Add(new Student() { StuNo = "002", StuName = "李四" }); list.Add(new Student() { StuNo = "003", StuName = "王五" }); return list; } //返回DataSet [WebMethod] public DataSet GetDataSet() { DataSet ds = new DataSet(); DataTable dt = new DataTable(); dt.Columns.Add("StuNo", Type.GetType("System.String")); dt.Columns.Add("StuName", Type.GetType("System.String")); DataRow dr = dt.NewRow(); dr["StuNo"] = "001"; dr["StuName"] = "张三"; dt.Rows.Add(dr); dr = dt.NewRow(); dr["StuNo"] = "002"; dr["StuName"] = "李四"; dt.Rows.Add(dr); ds.Tables.Add(dt); return ds; } } public class Student { public string StuNo { get; set; } public string StuName { get; set; } } }
3、在WebService的web.config文件的system.web节下面加上以下配置。如果不添加在运行手工发送HTTP请求调用WebService(利用GET方式)时,总是出现“远程服务器返回错误: (500) 内部服务器错误。”就是这个该死的错误,让我浪费2个多小时
<webServices> <protocols> <add name="HttpPost" /> <add name="HttpGet" /> </protocols> </webServices>
4、在WinForm应用程序里添加Web引用,有人会发现选择WinForm项目里只能添加服务引用,我当初也是这么认为后来,后来发现在做异步的调用的时候有些方法实在点不出来,所以这里说下如何添加Web引用,选择项目WinFormInvokeWebService右键->添加服务引用,弹出以下对话框
(1)选择高级
(2)选择添加web引用
(3)选择“此解决方案中的Web服务”
(4)选择Service1
(5)在web引用名里输入一个服务名称,这里使用默认的名称localhost,点添加引用
5、添加3个Windows窗体,
(1)Form1拖放的控件为:
Form1的代码为:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WinFormInvokeWebService { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { localhost.Service1 service = new localhost.Service1(); localhost.Student s = service.GetStudentByStuNo("002"); MessageBox.Show("学号:" + s.StuNo + ",姓名:" + s.StuName); } private void button2_Click(object sender, EventArgs e) { new Form2().Show(); } private void button3_Click(object sender, EventArgs e) { new Form3().Show(); } } }
(2)Form2拖放的控件为:
Form2的代码为:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; //导入此命名空间 using System.Net; using System.Xml; using System.IO; using System.Web; //先添加System.Web引用再导入此命名空间 namespace WinFormInvokeWebService { public partial class Form2 : Form { public Form2() { InitializeComponent(); } //手工发送HTTP请求调用WebService-GET方式 private void button1_Click(object sender, EventArgs e) { //http://localhost:3152注意你的地址可能和我的不一样,运行WebService看下你的端口改下 string strURL = "http://localhost:3152/Service1.asmx/GetStudentByStuNo?stuNo="; strURL += this.textBox1.Text; //创建一个HTTP请求 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(strURL); //request.Method="get"; HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse(); Stream s = response.GetResponseStream(); XmlTextReader Reader = new XmlTextReader(s); Reader.MoveToContent(); string strValue = Reader.ReadInnerXml(); strValue = strValue.Replace("<", "<"); strValue = strValue.Replace(">", ">"); MessageBox.Show(strValue); Reader.Close(); } //手工发送HTTP请求调用WebService-POST方式 private void button2_Click(object sender, EventArgs e) { //http://localhost:3152注意你的地址可能和我的不一样,运行WebService看下你的端口改下 string strURL = "http://localhost:3152/Service1.asmx/GetStudentByStuNo"; //创建一个HTTP请求 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(strURL); //Post请求方式 request.Method = "POST"; //内容类型 request.ContentType = "application/x-www-form-urlencoded"; //参数经过URL编码 string paraUrlCoded = HttpUtility.UrlEncode("stuNo"); paraUrlCoded += "=" + HttpUtility.UrlEncode(this.textBox1.Text); byte[] payload; //将URL编码后的字符串转化为字节 payload = System.Text.Encoding.UTF8.GetBytes(paraUrlCoded); //设置请求的ContentLength request.ContentLength = payload.Length; //获得请求流 Stream writer = request.GetRequestStream(); //将请求参数写入流 writer.Write(payload, 0, payload.Length); //关闭请求流 writer.Close(); //获得响应流 HttpWebResponse response = (HttpWebResponse)request.GetResponse(); Stream s = response.GetResponseStream(); XmlTextReader Reader = new XmlTextReader(s); Reader.MoveToContent(); string strValue = Reader.ReadInnerXml(); strValue = strValue.Replace("<", "<"); strValue = strValue.Replace(">", ">"); MessageBox.Show(strValue); Reader.Close(); } } }
(3)Form3拖放的控件为:
Form3的代码为:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WinFormInvokeWebService { public partial class Form3 : Form { public Form3() { InitializeComponent(); } //利用Backgroundworker对象 private void button1_Click(object sender, EventArgs e) { BackgroundWorker backgroundworker = new BackgroundWorker(); // 注册具体异步处理的方法 backgroundworker.DoWork += new DoWorkEventHandler(back_DoWork); // 注册调用完成后的回调方法 backgroundworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(back_RunWorkerCompleted); // 这里开始异步调用 backgroundworker.RunWorkerAsync(); //调用服务的同时客户端处理并不停止 ChangeProcessBar(); } //完成事件 void back_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Error != null) throw e.Error; progressBar1.Value = progressBar1.Maximum; //调用完成了,把客户端进度条填充满 localhost.Student s = e.Result as localhost.Student; //获取处理结果 MessageBox.Show("学号:" + s.StuNo + ",姓名:" + s.StuName); //显示从服务器获取的结果值 } //调用方法 void back_DoWork(object sender, DoWorkEventArgs e) { // Web Service代理类 localhost.Service1 service = new localhost.Service1(); // 调用Web方法GetClass1,结果赋值给DoWorkEventArgs的Result对象 e.Result = service.GetStudentByStuNo("002"); } /// <summary> /// 界面的进度条显示 /// </summary> void ChangeProcessBar() { for (int i = 0; i < 10; i++) { progressBar1.Value = i; System.Threading.Thread.Sleep(500); } } //调用WebMethod的Async方法 private void button2_Click(object sender, EventArgs e) { // Web Service代理类 localhost.Service1 service = new localhost.Service1(); //这里开始异步调用 //service.GetProductPriceAsync("001"); service.GetStudentByStuNoAsync("002"); // 注册调用完成后的回调方法 service.GetStudentByStuNoCompleted += new localhost.GetStudentByStuNoCompletedEventHandler(GetStudentByStuNoCompleted); //调用同时客户端处理不停止 ChangeProcessBar(); } //完成事件 void GetStudentByStuNoCompleted(object sender, localhost.GetStudentByStuNoCompletedEventArgs e) { if (e.Error != null) throw e.Error; progressBar1.Value = progressBar1.Maximum; //调用完成了,把客户端进度条填充满 localhost.Student s = e.Result as localhost.Student; //获取处理结果 MessageBox.Show("学号:" + s.StuNo + ",姓名:" + s.StuName); //显示从服务器获取的结果值 } } }
运行结果: