Introduction
This article will explain how to consume an ASMX service using AngularJS. The scope of this article is limited to illustrate a simple example of creating and consuming JSON ASMX services using AngularJS. Pitfalls personally faced by the author, being new to both Web Services and AngularJS, are highlighted in this article to spare our fellow beginners the "start-up" agony. It is to be noted that ASMX web service is now a legacy technology. Recently, more advanced technologies are used to build Web Services with better performance.
To build our sample application, we have used AngularJS version 1.2.16. This article demonstrates how AngularJS will retrieve a list of Questions from a database. The ASMX web service is hosted in the same web application. In this example, I used ASPX Webform and an MSAccess backend, but you can use HTML page instead of the Webform and, of course, any database.
For calling the service, we need to use the $http.get()
method of AngularJS, which sends a Request
to the server. The ASMX service then sends a response in JSON format, that will be parsed and consumed in AngularJS.
Definitions
JSON (JavaScript Object Notation) is a lightweight, language independent, data-interchange format. JSON is syntax for storing and exchanging text information. JSON is smaller than XML, faster and easier to parse. [1,2]
A Web Service is a method of communication between two electronic devices over any network. It is designed to allow applications built using different technologies to communicate with each other using international standards.
AngularJS "lets you extend HTML vocabulary for your application. The resulting environment is extraordinarily expressive, readable, and quick to develop." [3]
Using the Code: Step by Step
The business logic of the sample application is quite simple. The QuestionID
and QuestionText
were stored in Questions
table in Quiz.mdb. When the service Web Method is invoked, the service connects to the database, retrieves a list of questions as a DataTable
, uses System.Web.Script.Serialization.JavaScriptSerializer()
method to Convert DataTable
to JSON String
, and finally, supplies a list of Questions
to be returned in JSON format.
Step (1) Create a New Web Application
Create a new Web Site, then create a new ASMX Web Service and a new WebForm or new HTML page.
Step (2) Create a Simple Database
In this example, I used MSAccess. You can use any database, of course. you will only need to change the connection string.
Step (3) Write the Code for your Business Logic
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;
}
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);
}
Step (4) Setup your [WebMethod]
The definition of the Web Method makes it enabled for invoking. Also setup the Response.ContentType
to be in JSON format.
[WebService(Namespace = "AnyNameSpace")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService
{
[WebMethod]
[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;
}
}
Step (5) Test your Web Service
Run the Code and Click "Invoke". If you have done everything properly, you should see a message like this:
It is important to note that you have to use the data.Message
not only data
in HelloWorld()
If, you use data
not data.Message
you will not get an error (initially), but you will experience a run time error because AngularJS will fail to parse it.
Step (6) Define the Configuration in web.config
Define the webServices
protocols under the section <system.web>
.
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
Failing to configure the webServices
section properly might lead to the following error:
Step (7) Prepare Your WebForm (or HTML Page)
The Directive ng-app
is used to "auto-bootstrap" an AngularJS application. The questionsController
will get the data from the $scope
, which in turn gets its data from $http.get()
function and parses the message content using JSON.parse()
method. Pitfalls include the wrong placing of directives and the improper parsing of 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>
Step (8) Running Your Application on a different Domain
If you run your service consuming application on a domain different from the domain providing the webservice, you might face an "Access-Control" error.
In this case, adding the following section to Web.config will solve this issue.
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Headers" value="Content-Type"/>
</customHeaders>
</httpProtocol>
</system.webServer>
References