C#通过构造Soap信息使用HttpWebRequest调用WebService

来源:互联网 发布:python软件开发 编辑:程序博客网 时间:2024/05/19 13:19

一、遇到的问题

1.在此之前没有使用Soap+HttpWebRequest过这种调用WebService的方式,对其中的概念不是很理解,能了解个大概
2.调用的WebService是用java开发的,需要自己构造Soap信息(当然,对方给了Soap格式)
3.该WebService启用了身份验证(在浏览器地址栏输入WebService地址,会弹出窗口要求输入用户名密码)

二、我之前如何用C#调用接口

1.添加服务引用

打开Visual Studio的解决方案资源管理器>>鼠标右键引用>>添加服务引用>>输入接口地址点击跳转、确定,如下图所示:

2.实例化WebService

实例化之后就可以使用WebService包含的方法了,代码如下:
ServiceReference1.WebService1SoapClient webClient = new ServiceReference1.WebService1SoapClient();//实例化WebService

三、观察了解SOAP结构

1.在IIS上发布一个带有身份验证的WebService接口

打开IIS>>选中要操作的网站>>身份验证>>禁用匿名身份验证>>开启Windows身份验证,如下图所示:

2.在浏览器输入接口地址

弹出身份验证的验证框需要我们输入部署该接口的服务器的用户名和登陆密码,如下图所示:

3.登入接口

输入服务器(部署了接口的计算机)的用户名和开机密码登陆进入接口,如下图所示:
我们随便进入一个方法节点,这里以LoginAction登陆方法为例,进入后我们仔细观察的话会发现页面中有两段xml文档,注意!!这两段xml分别就是SOAP的请求和响应示例!!我们一会儿在后面会用到这两个SOAP!!如下图所示:

4.观察SOAP结构

我们来观察一下这个SOAP请求的结构,其中所显示的占位符是我们需要替换的实际要传输的值,格式如下:
POST /WebService1.asmx HTTP/1.1Host: localhostContent-Type: text/xml; charset=utf-8Content-Length: lengthSOAPAction: "http://tempuri.org/LoginAction"<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">  <soap:Body>    <LoginAction xmlns="http://tempuri.org/">      <pin>string</pin>      <pas>string</pas>    </LoginAction>  </soap:Body></soap:Envelope>

好了,到这里我们知道了要构造要传输的SOAP信息后,我们就可以用HttpWebRequest来和接口进行通信了,步骤及代码请继续往下看。

四、使用C#调用带有身份验证的WebService的测试

都在代码(酒)里,干杯!!
using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Net;using System.ServiceModel.Description;using System.Text;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;namespace testwebservice{    public partial class WebForm1 : System.Web.UI.Page    {                //ServiceReference1.WebService1SoapClient webClient = new ServiceReference1.WebService1SoapClient();        protected void Page_Load(object sender, EventArgs e)        {        }        protected void login_Click(object sender, EventArgs e)        {            /*本页面一共三个服务器控件:两个TextBox用于接收用户名密码,一个Button触发点击事件             */            string uname = this.username.Text;//获取页面上的用户名            string pwd = this.password.Text;  //获取密码            //按照前面描述的SOAP结构,构造SOAP信息            string soap = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +                          "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +                              "<soap:Body>" +                                  "<LoginAction xmlns=\"http://tempuri.org/\">" +                                      "<pin>"+uname+"</pin>" +                                      "<pas>"+pwd+"</pas>" +                                  "</LoginAction>" +                              "</soap:Body>" +                          "</soap:Envelope>";            //将SOAP字符串信息转换成Byte数组,用于后面的流传输            byte[] bytData = Encoding.UTF8.GetBytes(soap.ToString());            //创建一个HttpWebRequest实例,地址http://localhost:7887/WebService1.asmx是我发布到本地IIS上的接口            HttpWebRequest request = System.Net.WebRequest.Create(new Uri("http://localhost:7887/WebService1.asmx")) as HttpWebRequest;            //按照SOAP结构中描述的给各个属性赋值            request.Method = "POST";//POST方式传输            request.Host = "localhost";//主机名或IP地址            request.ContentType = "text/xml; charset=utf-8";//传输内容类型及编码格式            request.ContentLength = bytData.Length;//传输内容长度            //注意这里的SOAPAction,看它的value值,是指向了默认命名空间下的LoginAction方法            //通常成熟的接口中都有自定义的SOAP节点(我认为),来告诉服务我要调用那个方法,所以在这种情况下我们把这里的SOAPAction的value值置成空            //(如果你不明白的话,请忽略上面那句话,总之你要知道SOAPAction就是告诉服务我们要调用哪个接口方法)            request.Headers.Add("SOAPAction", "http://tempuri.org/LoginAction");                        //注意!!这里就是身份验证!!如果没有认证,但是IIS却开启了Windows身份验证,就会报401错误!!切记!!            request.Credentials = MyCred();            request.Timeout = 100000;//设置超时时间            //用GetRequestStream()方法来获取一个流,它发出的请求将数据发送到Internet资源供给接口            Stream newStream = request.GetRequestStream();            //将数据写入该流            newStream.Write(bytData, 0, bytData.Length);//写入参数            newStream.Close();            //服务响应            HttpWebResponse res;            try            {                //获取一个响应                res = (HttpWebResponse)request.GetResponse();            }            catch (WebException ex)            {                res = (HttpWebResponse)ex.Response;            }            //将响应写入StreamReader            StreamReader sr = new StreamReader(res.GetResponseStream(), Encoding.UTF8);            //读取流转换成字符串            string ret = sr.ReadToEnd();            //关闭资源            sr.Close();            res.Close();            newStream.Close();        }        /// <summary>        /// 服务器网络凭证        /// </summary>        /// <returns></returns>        public static NetworkCredential MyCred()        {            string loginUser = Properties.Settings.Default.UserName;//用户名            string loginPSW = Properties.Settings.Default.UserPSW;//密码            string loginHost = Properties.Settings.Default.HostName;//主机名,可以是IP地址,也可以服务器名称            NetworkCredential myCred = new NetworkCredential(loginUser, loginPSW, loginHost);            return myCred;        }    }}
注意!!如果代码里没有认证,但是IIS却开启了Windows身份验证,就会报401错误!!Check it out!!yoo~what's up!!