Fork me on GitHub
调用远程服务的几种实现方式

谈一谈调用远程服务的几种实现方式

也许在我们过往的项目开发过程当中,或多或少都会遇到过针对于现有系统信息进行整合,使用的需求,或是调用人家接口或是给人家提供服务,今天就简单的和大家一起分享一些可用的远程调用服务的方法:

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操作。

目前来看有这几种比较成熟的方法,个人比较喜欢最后一种。

分类: js/前端
posted on 2013-10-21 11:19  HackerVirus  阅读(1204)  评论(0编辑  收藏  举报