Introduction
The scope of this article is to show a little example about REST web services and how to use it in a typical web application with AJAX and Javascript.
To do this, we create, with Visual Studio 2010, a typical gridview
with Microsoft.NET and a WCF web service REST-enabled. The gridview
uses Ajax to retrieve data from this web service. We populate the gridview
and, by clicking a “detail” button for each single item of the gridview
, we invoke the REST Web Service asynchronously, with JavaScript, directly from the browser, filling a detail panel.
Using the Code
In the solution, we find the following components:
- A first WCF web service that uses SOAP protocol
- A second WCF web service that uses REST protocol
- A simple Web application that contains a
gridview
populated by the first WCF web service SOAP-enabled - The coolest function: an enhancement of the
gridview
, by adding client-side detail panels that are able to invoke asynchronously the second Web Service REST-enabled
In the following, I explain each project contained in the solution, showing main classes and main points of interest.
Project "WCFCustomerService"
Service "CustomerService.svc"
This is a classic WCF service SOAP-enabled that retrieves the list of customers from database. In the code, I used "EntityFramework
" to retrieve data by exposing to the external world directly the business object "Customers
". This object was created automatically by Visual studio adding an "ADO.NET Entity Data Model" to the project. You can find it in the project, with the name "WcfDatabaseModel.edmx". The main piece of code is this:
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Allowed)]
public class CustomersService : ICustomersService
{
public List <CUSTOMERS> GetCustomersList()
{
WCFCustomerServiceDatabaseEntities entities =
new WCFCustomerServiceDatabaseEntities();
return entities.CUSTOMERS.ToList<CUSTOMERS>();
}
}
Service "RESTOrdersService.svc"
This is the WCF service REST-enabled. The code of this service shows some new keywords that enable WCF to serialize answers with JSON notation. The main piece of code is this:
[ServiceContract(Namespace = "WcfCustomerService")]
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Allowed)]
public class RESTOrdersService
{
[OperationContract]
[WebGet(ResponseFormat=WebMessageFormat.Json)]
public OrdersJSON[] GetOrdersDetailsForCustomer(long idCustomer)
{
WCFCustomerServiceDatabaseEntities entities =
new WCFCustomerServiceDatabaseEntities();
List<ORDERS> tmpList = entities.ORDERS.Where
(x => x.FK_IDCUSTOMER == idCustomer).ToList<ORDERS>();
List<OrdersJSON> ordersForCustomer = new List<OrdersJSON>();
foreach (var item in tmpList)
{
ordersForCustomer.Add(new OrdersJSON(item.ID, item.DESCRIPTION));
}
return ordersForCustomer.ToArray<OrdersJSON>();
}
}
Check the attribute "[WebGet]
". This attribute enables WCF to accept REST calls. In the code of the web application, we'll see the way to do these calls (JavaScript does everything for us).
Another interesting point is the use of Linq retrieving data from the Entity Model. A simple inline query written in lambda notation today replaces various lines of code and various objects used in the recent past (SqlCommand
, SqlConnection
, query SQL). This query filters all the orders for a specific customer ID that we provide when calling the web service.
Object OrdersJSON
We need to give particular attention to the object returned from the function "GetOrdersDetailsForCustomer
". This function returns the object "OrdersJSON
" that is an object created by me. In this object, I marked attributes with specific tags [DataContract]
and [DataMember]
that allows WCF to serialize the object in JSON notation. This is the code of my object:
[DataContract]
public class OrdersJSON
{
[DataMember]
public long Id { get; set; }
[DataMember]
public string OrderDescription {get;set;}
public OrdersJSON(long pId, string pOrderDescription) {
Id = pId;
OrderDescription = pOrderDescription;
}
}
Notes about Web.config File
As for the web.config file, I want to show some particular setting we need to know. To enable REST capabilities, the "behavior" section in the web.config needs the attribute <enableWebScript>
. This is the section where we use this attribute:
<endpointBehaviors>
<behavior name="WcfCustomerService.RESTOrdersServiceAspNetAjaxBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
But also check the definition of the endpoint. The binding needs to be set to webHttpBinding
value.
<service name="WcfCustomerService.RESTOrdersService">
<endpoint address="" behaviorConfiguration=
"WcfCustomerService.RESTOrdersServiceAspNetAjaxBehavior"
binding="webHttpBinding" contract="WcfCustomerService.RESTOrdersService" />
</service>
Web Project "WebAppSampleGridview"
This is a default ASP.NET empty project created with Visual Studio 2010. I added a page that contains the gridview
and a ServiceReference
to the WCF Service "CustomerService.cs".
To invoke the REST Web service ("RestOrdersService
"), we don't need to add any ServiceReference
. We need to modify some attribute in the "Web.config" file of the web application. The call will be done from JavaScript. I show the main pieces of JavaScript code and ASP.NET tags that allows this call. You can find it in the default.aspx page.
The first important thing is to add a tag ServiceReference
to the ScriptManager
tag contained in the page. This ServiceReference
tag specifies the address of the REST Web service.
<asp:ScriptManager ID="ScriptManager1" runat="server" >
<Services >
<asp:ServiceReference Path="http://localhost:1193/RESTOrdersService.svc"/ >
</Services >
</asp:ScriptManager >
This section, instead, contains the JavaScript code that executes the call to the RESTOrdersService
.
<script type="text/javascript">
function buttonInvokeWebService(idCustomer, caller)
{
var service = new WcfCustomerService.RESTOrdersService();
service.GetOrdersDetailsForCustomer(idCustomer, onSuccess, onFailure);
document.getElementById("detailPanel").style.visibility = "visible";
return false;
}
function onSuccess(result) {
var myArrayJsonObjects = eval(result);
document.getElementById("orderCount").innerHTML = myArrayJsonObjects.length;
if (myArrayJsonObjects.length > 0)
document.getElementById("orderDescription").innerHTML =
myArrayJsonObjects[0].OrderDescription
else
document.getElementById("orderDescription").innerHTML = "";
}
function onFailure(result) {
context.innerText = "Error Invoking the Web Service...";
}
</script>
The function "buttonInvokeWebService
" is called from a button
in the gridview
. To invoke the RestOrdersService
, we need only declare it and invoke the function. Note that we must define two functions: "onSuccess
" and "onFailure
" that contain the result returned from the REST service and manages possible errors. In this example, the "onSuccess
" function puts the result in an element called "orderDescription
" and is inserted in the page. The function also shows a panel that contains the result, by setting his visibility to "visible
".
An important note: The scope of this article it is not to show special effects with JavaScript. For this reason, the code in these functions is very rough: I prefer to keep the focus on how to manage REST calls and not on how to show data in nice way.
History
- 08.29.2010 - First release