65.9K
CodeProject 正在变化。 阅读更多。
Home

消费 ASMX Web 服务与 AngularJS:初学者的“体验”!

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.97/5 (20投票s)

2014年5月24日

CPOL

3分钟阅读

viewsIcon

127515

downloadIcon

2662

一个循序渐进的教程,展示了如何使用 AngularJS 从应用程序调用 ASMX 服务,并突出显示常见的陷阱。

引言

本文将解释如何使用 AngularJS 调用 ASMX 服务。本文的范围仅限于演示使用 AngularJS 创建和调用 JSON ASMX 服务的简单示例。作者作为 Web 服务和 AngularJS 的新手,亲身经历的陷阱将在本文中突出显示,以使我们的初学者免受“启动”的痛苦。需要注意的是,ASMX Web 服务现在是一种遗留技术。最近,更多高级技术用于构建具有更好性能的 Web 服务。

为了构建我们的示例应用程序,我们使用了 AngularJS 版本 1.2.16。本文演示了 AngularJS 如何从数据库中检索问题列表。 ASMX Web 服务托管在同一个 Web 应用程序中。在此示例中,我使用了 ASPX Webform 和 MSAccess 后端,但你可以使用 HTML 页面代替 Webform,当然,也可以使用任何数据库。

为了调用服务,我们需要使用 AngularJS 的 $http.get() 方法,它向服务器发送一个 Request。然后,ASMX 服务以 JSON 格式发送响应,该响应将在 AngularJS 中进行解析和使用。

定义

JSON(JavaScript 对象表示法)是一种轻量级的、与语言无关的数据交换格式。 JSON 是存储和交换文本信息的语法。 JSON 比 XML 更小、更快且更易于解析。[1,2]

Web 服务是两个电子设备通过任何网络进行通信的一种方法。它旨在允许使用不同技术构建的应用程序使用国际标准相互通信。

AngularJS “允许您扩展应用程序的 HTML 词汇表。 生成的环境非常具有表现力、可读性且开发速度快。”[3]

使用代码:逐步说明

示例应用程序的业务逻辑非常简单。 QuestionIDQuestionText 存储在 Quiz.mdb 中的 Questions 表中。当调用服务 Web 方法时,该服务连接到数据库,检索问题列表作为 DataTable,使用 System.Web.Script.Serialization.JavaScriptSerializer() 方法将 DataTable 转换为 JSON String,最后,提供一个以 JSON 格式返回的 Questions 列表。

步骤 (1) 创建一个新的 Web 应用程序

创建一个新的 Web 站点,然后创建一个新的 ASMX Web 服务和一个新的 WebForm 或新的 HTML 页面。

步骤 (2) 创建一个简单的数据库

在此示例中,我使用了 MSAccess。 当然,你可以使用任何数据库。 你只需要更改连接字符串。

步骤 (3) 编写您的业务逻辑代码

// in this sample, and as described in the article, 
// this is a simple method that will connect to the database, 
// execute an SQL command and return data in form of a DataTable 
public DataTable GetDataTable()
    {
        DataTable dataTable = new DataTable();
        using (OleDbConnection conn = new OleDbConnection
        ("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=|DataDirectory|Quiz.mdb"))
        {
            OleDbCommand cmd = conn.CreateCommand();
            cmd.CommandText = "select * from Questions";

            cmd.CommandType = CommandType.Text;

            if (conn.State != ConnectionState.Open)
                conn.Open();

            OleDbDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);

            dataTable.Load(dr);
        }
        return dataTable;
    }
//once the datatable is ready, it has to be converted to JSON to be consumable with AngularJS, 
//the following function uses Javascript serializer to do the conversion

    public String ConvertDataTableTojSonString(DataTable dataTable)
    {
        System.Web.Script.Serialization.JavaScriptSerializer serializer =
               new System.Web.Script.Serialization.JavaScriptSerializer();

        List<Dictionary<String, Object>> tableRows = new List<Dictionary<String, Object>>();

        Dictionary<String, Object> row;

        foreach (DataRow dr in dataTable.Rows)
        {
            row = new Dictionary<String, Object>();
            foreach (DataColumn col in dataTable.Columns)
            {
                row.Add(col.ColumnName, dr[col]);
            }
            tableRows.Add(row);
        }
        return serializer.Serialize(tableRows);
    }  

步骤 (4) 设置您的 [WebMethod]

Web 方法的定义使其能够被调用。 此外,将 Response.ContentType 设置为 JSON 格式。

[WebService(Namespace = "AnyNameSpace")]

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, 
// uncomment the following line. 
[System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService

{  
// Business Logic Code goes here

[WebMethod] // by writing this line, you tell your service to enable this method / function 
  //for public consumption. If you remove this line, the method can not be invoked.
    [ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
    public void HelloWorld()
    {
        JavaScriptSerializer js = new JavaScriptSerializer();
        Context.Response.Clear();
        Context.Response.ContentType = "application/json";
        HelloWorldData data = new HelloWorldData();
        data.Message = ConvertDataTableTojSonString(GetDataTable());
        Context.Response.Write(js.Serialize(data.Message));
    }

    public class HelloWorldData
    {
        public String Message;
    }
}

步骤 (5) 测试您的 Web 服务

运行代码并单击“Invoke”。 如果您已正确完成所有操作,则应该看到类似这样的消息

重要的是要注意,您必须使用 data.Message 而不仅仅是 HelloWorld() 中的 data

如果您使用 data 而不是 data.Message,您不会(最初)遇到错误,但您会遇到运行时错误,因为 AngularJS 将无法解析它。

步骤 (6) 在 web.config 中定义配置

<system.web> 部分下定义 webServices 协议。

<webServices>
   <protocols>
        <add name="HttpGet"/>
        <add name="HttpPost"/>
   </protocols>
</webServices> 

未能正确配置 webServices 部分可能会导致以下错误

步骤 (7) 准备您的 WebForm(或 HTML 页面)

指令 ng-app 用于“自动引导” AngularJS 应用程序。 questionsController 将从 $scope 获取数据,而 $scope 又从 $http.get() 函数获取其数据并使用 JSON.parse() 方法解析消息内容。 陷阱包括指令的错误放置和 JSON 的不正确解析。

<html ng-app="serviceConsumer">
<head runat="server">
    <title>consume JSON web service</title>
    <script src="js/angular.js"></script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <div ng-controller="questionsController">
            search:<input type="text" ng-model="search" />
            <table>
                <tr ng-repeat="i in questions | filter:search">
                    <td>
                        {{i.QuestionID}}
                    </td>
                    <td>
                        {{i.QuestionText }}
                    </td>
                </tr>
            </table>
        </div>
        <br />
    </div>
    <script>

        var app = angular.module('serviceConsumer', []);

        app.controller('questionsController', function ($scope, $http) {

            var url = "WebService.asmx/HelloWorld";

            $http.get(url)
                       .success(function (data) {

                           var myjson = JSON.parse(data);

                           $scope.questions = JSON.parse(myjson);

                       })
        })
                         
    </script>
    </form>
</body>
</html>  

步骤 (8) 在不同的域上运行您的应用程序

如果您在与提供 Web 服务的域不同的域上运行您的服务调用应用程序,您可能会遇到“Access-Control”错误。

在这种情况下,将以下部分添加到 Web.config 将解决此问题。

<system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*"/>
        <add name="Access-Control-Allow-Headers" value="Content-Type"/>
      </customHeaders>
    </httpProtocol>
  </system.webServer>

 

参考文献

© . All rights reserved.