WebService简单使用
WebServices:简单理解--解决了不同平台之间应用程序间通信的问题,数据以XML格式在程序间传输
实际的应用场景:例如 比价网 为什么比价网可以从众多的电商站点获得用户搜索的产品数据?WebServices就可以实现(注意:是“可以实现”,我并没有确切的说就是这么实现,也许有其他的方法)
2.再添加一个检索数据的方法:SearchProduct(string searchKey){}
using System.Collections.Generic; using System.Web.Services; namespace 提供WebService服务 { /// <summary> /// ComplexCalculate 的摘要说明 /// </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 ComplexCalculate : System.Web.Services.WebService { [WebMethod]//默认的WebServices服务 public string HelloWorld() { return "Hello World"; } //假设这是京东提供外部应用程序 访问自己数据的服务 //根据用户搜索关键字 返回检索结果 private readonly Dictionary<string, string> dictionary = new Dictionary<string, string>(); [WebMethod]//特性表明该方法可供外部访问 public string SearchProduct(string searchKey) { dictionary.Add("mx2", "联通MX2 京东"); dictionary.Add("小米2", "小米四核 京东");//模拟数据 dictionary.Add("MeiZu", "MeiZu标准本 京东"); return dictionary[searchKey]; } } }
3.直接运行ComplexCalculate.asmx可以看到
Chrome浏览器返回如下
其实无论返回什么样的数据,都会以XML格式包装输出,也正是由于任何平台都认识XML,解决了数据的跨平台通信问题,
当然现在Json慢慢的变为行业标准,已成为XML的替代品
4.外部站点 "调用WebServices服务" 调用localhost:1088检索服务时 首先添加服务引用 如图:
像我这种 提供WebServices服务 与 调用WebServices服务 在同一解决方案下 直接点击发现就可以了(如果是互联网上的WebServices,那将提供的asmx地址复制到地址框中,点击前往,就可以得到服务).确定后,会将该服务相关的配置信息写入Web.Config中,如下:
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <compilation debug="true" targetFramework="4.0" /> </system.web> <system.serviceModel> <bindings> <basicHttpBinding> <binding name="ComplexCalculateSoap" /> <binding name="NeedValidateWsSoap" /> </basicHttpBinding> </bindings> <client> <endpoint address="http://localhost:1808/ComplexCalculate.asmx" binding="basicHttpBinding" bindingConfiguration="ComplexCalculateSoap" contract="SimpleUse.ComplexCalculateSoap" name="ComplexCalculateSoap" /> <endpoint address="http://localhost:1808/NeedValidateWS.asmx" binding="basicHttpBinding" bindingConfiguration="NeedValidateWsSoap" contract="AuthenticationPage.NeedValidateWsSoap" name="NeedValidateWsSoap" /> </client> </system.serviceModel> </configuration>
关于,第2和3步做什么,待续,图先放这。
5.使用WebServices的SimpleUse.aspx.cs代码如下:
using System; using 调用WebServices服务.SimpleUse; namespace 调用WebServices服务 { public partial class SimpleUsePage : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { //同步调用 using(SimpleUse.ComplexCalculateSoapClient client = new ComplexCalculateSoapClient()) { Response.Write(client.SearchProduct("mx2")); } } } }
运行后显示结果"联通 MX2 京东",当然前提是提供WebServices服务必须开启
是不是So easy!? 因为微软让它easy,如果是Java来做WebServices就没这么简单了!
使用互联网上免费的WebServices与上述大同小异,不啰嗦了.
异步调用WebServeices
上述WebServices服务狠简单,如果是一个狠复杂或者耗时的操作,那调用者岂不是要享受等待的煎熬?! 所以需要异步调用WebServices
异步调用有两种方式:
1.上图中添加索引服务时,有个"高级"选项,选择之后,弹出"服务引用设置",我们选择"生成异步操作"
操作的背后,微软帮我们针对SearchProduct方法生成了一个与之对应的异步方法SearchProductAncys方法
UseAsync.aspx.cs后台调用如下:
using System; using 调用WebServices服务.SimpleUse; namespace 调用WebServices服务 { public partial class UseAsync : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { using(SimpleUse.ComplexCalculateSoapClient client = new ComplexCalculateSoapClient()) { client.SearchProductCompleted += client_SearchProductCompleted; //委托 接收异步响应结果 } } void client_SearchProductCompleted(object sender, SearchProductCompletedEventArgs e) { Response.Write(e.Result);//输出异步返回结果 } } }
需要注意的是UseAsync.aspx页面需要添加Async=true;允许接收异步的配置
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="UseAsync.aspx.cs" Async="true" Inherits="调用WebServices服务.UseAsync" %>
2.第二种通过开启一个后台工作者,使用BackgroundWorker类,所属命名空间:using System.ComponentModel;
using System; using System.ComponentModel; using 调用WebServices服务.SimpleUse; namespace 调用WebServices服务 { public partial class AsyncByWorker : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { BackgroundWorker background = new BackgroundWorker(); //设置需要异步执行的操作 background.DoWork += background_DoWork; //接收异步操作结果的"回调函数" background.RunWorkerCompleted += background_RunWorkerCompleted; //开始真正的执行异步操作 不要遗漏 background.RunWorkerAsync(); } void background_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { Response.Write(e.Result);//从Result中获取结果 } void background_DoWork(object sender, DoWorkEventArgs e) { using(SimpleUse.ComplexCalculateSoapClient client = new ComplexCalculateSoapClient()) { e.Result = client.SearchProduct("mx2");//执行结果写入Result中 } } } }
前台同上需要设置Async=true;
WebServices验证
互联网上提供的免费WebServices是任何人都可以使用的,而有些则需要用户名、密码才能使用,这些验证是如何做到的呢?
方式有很多,这里只说我知道也是最简单的一种--通过Soap头传递用户名密码进行身份校验
步骤:
1.自定义MySelfSoapHeader继承SoapHeader 并具有用户名、密码、身份校验方法
2.在Services服务中添加SoapHeader特性及未初始化的MySelfSoapHeader实例
3.调用者对服务端MySelfSoapHeader实例化 同时为用户名密码赋值,提交至服务端
4.服务端返回验证结果
MySelfSoapHeader.cs具有Name、Pwd字段属性
校验方法如下
using System.Web.Services.Protocols; namespace 提供WebService服务 { public class MySelfSoapHeader : SoapHeader { private string _name; private string _pwd; public string Name {get {return _name;}set {_name = value;}} public string Pwd {get {return _pwd;}set {_pwd = value;} } private bool ValidaResult(string name, string pwd) { if(name == "pizi" && pwd == "yimao") { return true; } return false; } public bool GetResult() { return ValidaResult(_name, _pwd); } } }
添加NeedValidateWS服务
using System.Web.Services; using System.Web.Services.Protocols; namespace 提供WebService服务 { /// <summary> /// NeedValidateWS 的摘要说明 /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.ComponentModel.ToolboxItem(false)] public class NeedValidateWs : System.Web.Services.WebService { public MySelfSoapHeader MySoapHeader = null;//这里是通过客户端实例化的 不要new [SoapHeader("MySoapHeader")] [WebMethod(Description = "需要验证的方法")] public string IsValid() { if(MySoapHeader.GetResult()) { return "验证通过"; } return "未通过验证"; } } }
调用页面
using System; using 调用WebServices服务.AuthenticationPage; namespace 调用WebServices服务 { public partial class ValidPage : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { using(AuthenticationPage.NeedValidateWsSoapClient client = new NeedValidateWsSoapClient()) { MySelfSoapHeader header = new MySelfSoapHeader(); header.Name = "pizi"; header.Pwd = "yimao";//验证通过 //header.Pwd = "sanmao";//未通过验证 Response.Write(client.IsValid(header)); } } } }
这种验证方式存在数据的安全性问题,如果需要保证数据的安全性则使用加密算法或者SSL等验证方式,我了解的不多,所以不废话了
相关概念及资源
SOAP:简单对象访问协议,在分散或分布式的环境中交换信息的简单协议,基于XML协议
解决了三个问题:1.接口的自我描述;2.采用Http协议等常规协议,不用写原始的Socket;3.基于Web服务器,不占用80端口之外的端口.
Web Services平台元素
XML:可扩展标记语言,用来描述数据
WSDL:(WebService Defination Language)是对WebService上的方法名、参数进行描述的协议.对接口的自描述.SOAP:(Simple Object Access Protocol)对参数、返回值以什么样的格式进行传递进行描述的协议.对报文的格式规范.
SOAP和HTTP的关系:SOAP基于Http协议的,和普通网页不同的是网页返回HTML,SOAP则是符合SOAP协议的XML数据.
UDDI:用来自动发现WebService的协议
跨平台、跨语言调用,可以跨防火墙(基于Web服务器,不占用80端口之外的端口);
WebService缺点:
效率低.所以适用于两个非内部系统的通讯(比如炒股软件和证券交易所之间的通讯);
安全问题,Web Service的没有自身的安全机制,必须借助http协议或IIS等宿主程序实现信息安全加密
WCF是对WebService、Socket、MQ等通讯方式的一个统一,底层还是采用这些通信协议,可以简化这些程序的开发,不用再换不同通信协议的时候重写代码并且学一堆新的技术。所以WCF和WebService不是一个竞争取代关系。
WCF是对.Net Remoting、WebService、MQ等通讯方式的一个高级封装,让我们开发不同通讯协议的程序的时候很简单,不用学更多的东西。并不是替代.Net Remoting、WebService、MQ这些东西。
Web Services平台元素
XML:可扩展标记语言,用来描述数据
WSDL:(WebService Defination Language)是对WebService上的方法名、参数进行描述的协议.对接口的自描述.SOAP:(Simple Object Access Protocol)对参数、返回值以什么样的格式进行传递进行描述的协议.对报文的格式规范.
SOAP和HTTP的关系:SOAP基于Http协议的,和普通网页不同的是网页返回HTML,SOAP则是符合SOAP协议的XML数据.
UDDI:用来自动发现WebService的协议
跨平台、跨语言调用,可以跨防火墙(基于Web服务器,不占用80端口之外的端口);
WebService缺点:
效率低.所以适用于两个非内部系统的通讯(比如炒股软件和证券交易所之间的通讯);
安全问题,Web Service的没有自身的安全机制,必须借助http协议或IIS等宿主程序实现信息安全加密
当你的才华还撑不起你的野心时,那你就应该静下心来学习;当你的能力还驾驭不了你的目标时,那就应该沉下心来历练!