前言:
也许在我们过往的项目开发过程当中,或多或少都会遇到过针对于现有系统信息进行整合,使用的需求,或是调用人家接口或是给人家提供服务,今天就简单的和大家一起分享一些可用的远程调用服务的方法:
1.webservice方法
Web Service 是一种新的web应用程序分支,他们是自包含、自描述、模块化的应用,可以发布、定位、通过web调用。Web Service可以执行从简单的请求到复杂商务处理的任何功能。一旦部署以后,其他Web Service应用程序可以发现并调用它部署的服务。
实际上,WebService的主要目标是跨平台的可互操作性。为了达到这一目标,WebService完全基于XML(可扩展标记语言)、XSD(XMLSchema)等独立于平台、独立于软件供应商的标准,是创建可互操作的、分布式应用程序的新平台。
我相信大家都会有很多使用webservice的经验,首先说一下在web端调用同域下的webservice:
新建一个webservice,默认生成一个helloWord方法:
[WebMethod] public string HelloWorld() { return "Hello World"; }
之后我没在web端调用此服务:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script src="jquery.js" type="text/javascript"></script> <script type="text/javascript"> $(function () { $('#a_post').click(function () { postFun(); }); }); function postFun() { $.ajax({ type: "POST", //访问WebService使用post方式请求 contentType: "application/xml", //WebService会返回json类型 url: "http://localhost:1719/testaaa/MyWebService.asmx/HelloWorld", //调用WebService的地址和方法名称组合 dataType: "xml", success: function (data) { var html; if (typeof data == "string") { html = new ActiveXObject("Microsoft.XMLDOM"); html.loadXML(data); } else { html = data; } var $result = $(html).find("string"); var result = $result.text(); alert(result); } }) } </script> </head> <body> <input type="button" id="a_post" value="获取"/> </body> </html>
于是我们可以得到如下:
说明我们在web端调用同域下webservice成功。
于是我们会想是否可以以这种方法调用远程(不同域)下的webservice呢?
我明确的告诉你非常不容易,我一般的处理方式是在C#后台代码中调用这个服务,web端调用同域下的那个调用远程服务的后台服务就可以了,这其实是一种服务代理的方法,如果大家有什么好的实现web端调用远程webservice的方法,希望大家能够告诉我哦。
于是大家就会想:难道真的没有实现跨域调用服务的方法了吗?
方法还是有的,听我慢慢道来:
2:Jsonp
什么是JSONP JSONP是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。
Jsonp原理:
由于我们知道<script>标签是可以跨域的,所以我们就以动态生成<script>脚本的形式实现跨域请求:
首先在客户端注册一个callback, 然后把callback的名字传给服务器。
此时,服务器先生成 json 数据。
然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 jsonp.
最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。
客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里.(动态执行回调函数)
由于jsonp传送的形式是json形式,所以我们修改远程的服务:
using System; using System.Web; public class Handler : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; string callback = context.Request["callback"]; string response = string.Format("'value1':'{0}','value2':'{1}'", context.Request.QueryString["p1"], context.Request.QueryString["p2"]); string call = callback + "({" + response + "})"; context.Response.Write(call); } public bool IsReusable { get { return false; } } }
web端调用:
<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <script src="jquery.js" type="text/javascript"></script> <script type="text/javascript"> $(document).ready(function () { $('#a_post').click(function () { postFun(); }); }); var postFun = function () { jQuery.ajax({ type: "get", //url: "Jsonp_learn.aspx", url: "http://localhost:1719/testaaa/Handler.ashx", dataType: "jsonp", jsonp: "callback", data: "p1=1&p2=2", success: function (msg) { alert("value1:" + msg.value1 + " value2:" + msg.value2); } }); } </script> </head> <body> <input type="button" id="a_post" value="获取"/> </body> </html>
实现的结果:
OK,至此我们已经可以实现了我们的一些要求,当然程序员的特点就是永远希望找到最好的东西,并且与一切不简单,不美好的东西作斗争,我们思考一下以上两种实现方法的特点:
webservice:是以soap协议,xml形式调用的,web端调用我们需要将结果处理成xml;
jsonp:这是程序员思考的结晶,可是并没有一些官方的标准;
其实我们回想:何必这么麻烦不就是请求一个结果吗,一个字符串不久可以了?
3.restful
RESTful Wcf是一种基于Http协议的服务架构风格。 相较 WCF、WebService 使用 SOAP、WSDL、WS-* 而言,几乎所有的语言和网络平台都支持 HTTP 请求。
RESTful的几点好处:
1、简单的数据通讯方式,基于HTTP协议。避免了使用复杂的数据通讯方式。
2、避免了复杂的客户端代理。
3、直接通过URI资源定向即可把服务暴露给调用者。
REST 架构风格的流行。REST是一种简洁的设计风格,通过URL来设计系统,以URI来抽象各种资源,以HTTP协议的PUT,DELETE,GET,POST来对应对资源的各种操作。
于是我们决定用这种:既简单,由有一定的规范值得参考:
我们的实现可以依照wcf,具体实现大家可以google之,我们简单说一下.net的实现restful的比较好的方法webAPI:
我们通过vs傻瓜式的就建立了一个webapi:
Model:
public class TestUseMode { public string ModeKey{get;set;} public string ModeValue { get; set; } }
Controller:
MVC WebAPI中的Controllers和普通MVC的Controllers类似,不过不再继承于Controller,而改为继承API的ApiController,一个Controller可以包含多个Action,这些Action响应请求的方法与Global中配置的路由规则有关,在后面结束Global时统一说明.
public class TestController : ApiController { public static List<TestUseMode> allModeList = new List<TestUseMode>(); public IEnumerable<TestUseMode> GetAll() { return allModeList; } public IEnumerable<TestUseMode> GetOne(string key) { return allModeList.FindAll((mode) => { if (mode.ModeKey.Equals(key)) return true; return false; }); } public bool PostNew(TestUseMode mode) { allModeList.Add(mode); return true; } public int Delete(string key) { return allModeList.RemoveAll((mode) => { if (mode.ModeKey == key) return true; return false; }); } public int DeleteAll() { return allModeList.RemoveAll((mode) => { return true; }); } public int PutOne(string key, string value) { List<TestUseMode> upDataList = allModeList.FindAll((mode) => { if (mode.ModeKey == key) return true; return false; }); foreach(var mode in upDataList) { mode.ModeValue = value; } return upDataList.Count; } }
Global:
默认情况下,模板自带了两个路由规则,分别对应于WebAPI和普通MVC的Web请求,默认的WebAPI路由规则如下
1 routes.MapHttpRoute( 2 name: "DefaultApi", 3 routeTemplate: "api/{controller}/{id}", 4 defaults: new { id = RouteParameter.Optional } 5 );
简单使用JS调用上面提供的数据接口:
function getAll() { 2 $.ajax({ 3 url: "api/Test/", 4 type: 'GET', 5 success: function (data) { 6 document.getElementById("modes").innerHTML = ""; 7 $.each(data, function (key, val) { 8 var str = val.ModeKey + ': ' + val.ModeValue; 9 $('<li/>', { html: str }).appendTo($('#modes')); 10 }); 11 } 12 }).fail( 13 function (xhr, textStatus, err) { 14 alert('Error: ' + err); 15 }); 16 } 17 18 19 20 function add() { 21 22 $.ajax({ 23 url: "api/Test/", 24 type: "POST", 25 dataType: "json", 26 data: { "ModeKey": document.getElementById("txtKey").value, "ModeValue": document.getElementById("txtValue").value }, 27 success: function (data) { 28 getAll(); 29 } 30 }).fail( 31 function (xhr, textStatus, err) { 32 alert('Error: ' + err); 33 }); 34 35 } 36 37 function find() { 38 39 $.ajax({ 40 url: "api/Test/" + document.getElementById("txtFindKey").value, 41 type: 'GET', 42 success: function (data) { 43 document.getElementById("modes").innerHTML = ""; 44 $.each(data, function (key, val) { 45 var str = val.ModeKey + ': ' + val.ModeValue; 46 $('<li/>', { html: str }).appendTo($('#modes')); 47 }); 48 } 49 }).fail( 50 function (xhr, textStatus, err) { 51 alert('Error: ' + err); 52 }); 53 } 54 55 function removeAll() { 56 $.ajax({ 57 url: "api/Test/", 58 type: 'DELETE', 59 success: function (data) { 60 document.getElementById("modes").innerHTML = ""; 61 getAll(); 62 } 63 }).fail( 64 function (xhr, textStatus, err) { 65 alert('Error: ' + err); 66 }); 67 } 68 69 function remove() { 70 $.ajax({ 71 url: "api/Test/"+document.getElementById("txtRemoveKey").value, 72 type: 'DELETE', 73 success: function (data) { 74 document.getElementById("modes").innerHTML = ""; 75 getAll(); 76 } 77 }).fail( 78 function (xhr, textStatus, err) { 79 alert('Error: ' + err); 80 }); 81 } 82 83 function update() { 84 $.ajax({ 85 url: "api/Test/", 86 type: 'PUT', 87 dataType: "json", 88 data: { "key": document.getElementById("txtUpdateKey").value, "value": document.getElementById("txtUpdateValue").value }, 89 success: function (data) { 90 document.getElementById("modes").innerHTML = ""; 91 getAll(); 92 } 93 }).fail( 94 function (xhr, textStatus, err) { 95 alert('Error: ' + err); 96 }); 97 }
这样就实现了最基本的CRUD操作。
目前来看有这几种比较成熟的方法,个人比较喜欢最后一种。