Contents
- Visual Studio 2008 SP1
- .NET Framework 3.5 SP1
- ASP.NET AJAX
- IIS 7 or VS Integrated Web Server [WCF and SVS file configured]
- Windows Vista
WCF (Windows Communication Foundation) added a lot of new capabilities to the Microsoft application development platform, particularly in how applications communicate with each other. In this article, we are going to see how WCF can be used directly from a client-side JavaScript code. It is a very cool future provided by ASP.NET AJAX. In this article, we are not going to cover every theory about WCF internals, rather we only remain focused on how to use a service directly from JavaScript. So, no behind-the-scenes stuff on how ASP.NET or the .NET runtime manages this feature.
To demonstrate the ideas and facts, we are going create a demo solution with two projects. So, with no time waste, create a blank solution and save it. Now, add a Class Library project to the solution. Name the class library ServiceLibrary. Now, add a Web Application project to the solution and name it WEBUI. We are going to see two approaches to add a WCF Service that can be consumed from JavaScript.
- Using Ajax-Enable WCF Service item template
- Using Service Interface defined in a class library
Here, we will see a very straightforward way to use a WCF Service in JavaScript. Right click on the Web Application project and select Add New Item. Select AJAX-Enabled WCF Service Item Template, and name it “HelloWorldService.svc” and click OK. The wizard will add a HelloWorldService.svc file to the solution as expected. This file will have a code-behind file as well. If you open HelloWorldService.svc in an XML file editor, you will see a markup like this:
<%@ ServiceHost Language="C#" Debug="true"
Service="WebUI.HelloWorldService" CodeBehind="HelloWorldService.svc.cs" %>
If you open the code-behind file, you will see code like this:
namespace WebUI
{
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Allowed)]
public class HelloWorldService
{
[OperationContract]
public void DoWork()
{
return;
}
}
}
Visual Studio 2008 automatically adds the necessary configurations for you in the web.config file, so no need to configure any thing in the web.config. Now, go ahead and add a HelloWorld()
method which returns a string “HelloWorld”, and add a [OperationContract]
attribute to the method. We will explain what the attributes are later in this article. Now, add a page to the Web Application project and name it “HelloWorldTest.aspx”. Drag and drop a Script Manager item from the Visual Studio tool box. Inside the ScriptManager
tag, add a service reference to the service. An example code is given below:
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="~/HelloWorldService.svc" />
</Services>
</asp:ScriptManager>
Now, add a button and a textbox to the page, and on the button click event, use a JavaScript function to call the Service. When you write the service call function, the Visual Studio 2008 HTML Editor will provide intellisense to write the necessary function call. The full HTML code is give below:
<form id="form1" runat="server">
<div>
<script language="javascript" type="text/javascript">
function GetValueFromServer() {
HelloWorldService.HelloWorld(onSuccess, onFailure);
}
function onSuccess(result) {
document.getElementById('txtValueContainer').value = result;
}
function onFailure(result) {
window.alert(result);
}
</script>
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="~/HelloWorldService.svc" />
</Services>
</asp:ScriptManager>
<input id="btnServiceCaller" type="button" value="Get Value"
onclick="GetValueFromServer()"; />
<input id="txtValueContainer" type="text" value="" />
</div>
</form>
Note that when calling the service, we have passed two methods: one for the callback and the other for the error callback. If we need to pass any parameters to the function, the parameters will go first and then the callback. So, if we have a function named getvalue
which takes two string parameters as arguments, we are going to call the function as [NameSpaceName].[ServiceName].getvalue(“value one”,”value two”,on_success,on_error);, where on_sucess
and on_error
are the callback and the error callback, respectively.
So, we have looked at how to use an AJAX-enabled WCF Service using an item template. Now, we are going to see a more traditional WCF Service implementation, and we are also going to see how we can expose this service for ASP.NET AJAX. When we created the Class Library project, by default, it is not added with the service model and the runtime serialization support which is necessary to run WCF. So, we have to add the necessary service references. Go ahead and right click on the Class Library project and select Add Reference, and then select these references:
System.Runtime.Serialization
System.ServiceModel
In this phase, we are going to use a TODO Management example to demonstrate the whole idea. Add a Service based database, and then create a TODO table with ID
, Description
, and Status
fields. Now, add a LINQ to SQL class file from the item template. Drag and drop the TODO table from database to the LINQ to SQL Class File Designer. Now, click on the designer surface and from the property window, change the serialization mode to Unidirectional. Now, our designer generated LINQ to SQL classes are ready to be used for WCF. If you want to use custom user defined types, you must set the [DataContract]
class attribute to your class and you must add the [DataMember]
property attribute to each property of the class you want to expose to WCF.
Now, we are going to add a service interface like this:
namespace ServiceLibrary
{
[ServiceContract(Namespace = "ServiceLibrary")]
interface IToDoService
{
[OperationContract]
ToDo GetToDo(long ID);
[OperationContract]
ToDo AddToDo(ToDo toDo);
[OperationContract]
bool DeleteToDo(ToDo todo);
[OperationContract]
ToDo UpdateToDo(ToDo todo);
[OperationContract]
List<ToDo> GetAllToDo();
}
}
Note that we have mentioned a namespace inside the ServiceContract
interface attribute. This is very important. We are going to use this name as the service name inside the JavaScript code to access the services. Now, we are going to add the implementation to this service interface; the code is given below. Please note that in the code, I have used the [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
class attribute; this is a must requirement for exposing the service as an ASP.NET AJAX enabled WCF Service.
namespace ServiceLibrary
{
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Allowed)]
public class ToDoService : IToDoService
{
#region IToDoService Members
public ToDo GetToDo(long ID)
{
DataClasses1DataContext context = new DataClasses1DataContext();
var toDos = from p in context.ToDos
where p.ID == ID
select p;
List<ToDo> listTodos = toDos.ToList();
if (listTodos != null && listTodos.Count > 0)
{
return listTodos[0];
}
else
{
return null;
}
}
#endregion
}
}
Now that we have defined all the necessary stuff to run our TODO application, it is time to expose the Service to the client as an ASP.NET AJAX enabled WCF Service. For this, we are going to add an AJAX-enabled WCF Service .svc file. And, we will get rid of the code-behind file. Or, we can add an XML file or a text file and then rename it to ToDoService.svc. Open it with an XML editor and add a directive like shown below:
<%@ ServiceHost Language="C#" Debug="true" Service="ServiceLibrary.ToDoService" %>
Now, we are going to put the necessary configuration to run this service in web.config. The code is given below:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="AspNetAjaxBehavior">
<enableWebScript />
</behavior>
<behavior name="WebUI.HelloWorldServiceAspNetAjaxBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<services>
<service name="ServiceLibrary.ToDoService">
<endpoint behaviorConfiguration="AspNetAjaxBehavior" binding="webHttpBinding"
contract="ServiceLibrary.IToDoService" />
</service>
<service name="WebUI.HelloWorldService">
<endpoint address="" behaviorConfiguration="WebUI.HelloWorldServiceAspNetAjaxBehavior"
binding="webHttpBinding" contract="WebUI.HelloWorldService" />
</service>
</services>
</system.serviceModel>
Now, right click on the file and select View in Browser to see the service up and running well. A few things must be mentioned before moving to the next phase. You must add a serviceHostingEnvironment
and set aspNetCompatibilityEnabled="true"
to be able to use a WCF Service in ASP.NET with its features like HTTP Context, Session etc.
Now, use the service just like the HelloWorldService we previously used. Below, I have given example code to make things clear. The ScriptManager
markup is also shown. Note that we have added a clientServiceHelper.js file. We have put all the client to WCF communication JavaScript functions in that file.
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Scripts>
<asp:ScriptReference Path="~/Script/ClientServiceHeler.js" />
</Scripts>
<Services>
<asp:ServiceReference Path="~/ToDoService.svc" />
</Services>
</asp:ScriptManager>
We have used an ASP.NET AJAX client-side object oriented model to write the JavaScript client-code which is part of clientServiceHelper.js.
Type.registerNamespace("ServiceClients");
ServiceClients.ToDoClient = function() {
}
ServiceClients.ToDoClient.prototype = {
AddToDo: function(todo, callback, errorCallBack) {
ServiceLibrary.IToDoService.AddToDo(todo, callback, errorCallBack);
},
DeleteToDo: function(todo, callback, errorCallBack) {
ServiceLibrary.IToDoService.DeleteToDo(todo, callback, errorCallBack);
},
UpdateToDo: function(todo, callback, errorCallBack) {
ServiceLibrary.IToDoService.UpdateToDo(todo, callback, errorCallBack);
},
GetAllToDo: function(callback, errorCallBack) {
ServiceLibrary.IToDoService.GetAllToDo(callback, errorCallBack);
},
dispose: function() {
}
}
ServiceClients.ToDoClient.registerClass('ServiceClients.ToDoClient', null, Sys.IDisposable)
if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
In this article, we have seen how we can use an AJAX-enabled WCF Service Item Template. Then, we saw how we can use a service interface based WCF Service. We also saw how to configure the web.config to use the Services. Last of all, we saw how we to add a service reference in ScriptManager
. A few things must be mentioned before ending this article. We can also add a service reference in the C# code. A simple code example is given below:.
ScriptManager manager = ScriptManager.GetCurrent(Page);
ServiceReference reference = new ServiceReference("ToDoService.svc");
manager.Services.Add(reference);
If beginners encounter problems or do not understand any particular portion of the article, please drop me a message. You can learn the ABCs of WCF here. If you have any difficulty configuring WCF in IIS, please see the article here.