Implementing Auto Save Feature Using ASP.NET Ajax and WCF Service

Introduction

ASP.NET Ajax opens a lot of possibilities to provide users a rich user experience. At the
code level developers can create components, client behaviors or controls that
harness the power of ASP.NET and Ajax to provide features that are otherwise
difficult to offer. Ajax components are basically client side classes that
usually do not have any user interface. They inherit from Sys.Component base
class. Once inherited you can add your own properties, methods and events to
them in order to provide the necessary functionality. In this article you are
going to see how an Ajax component can be developed, that talks with the server side
data via a Windows Communication Foundation (WCF) service.

Example Scenario

Many web based email systems now a days offer a rich user interface. They
provide features such as automatically checking for new emails periodically and
automatically saving the messages you are still composing. The later feature can
be implemented in lengthy data entry forms. Imagine a scenario where a user is
presented with a lengthy data entry form. He starts filling the form and mid way
goes away for some other work. By the time he returns something causes the
browser to close or machine to restart (say a crash or power failure). Obviously
his data is lost since he didn't submit the form. Wouldn't it be nice if the web
form automatically saves the entered data on the server periodically so that the
web form state can be retrieved even after a crash? This is precisely what you
are going to develop in the remainder of the article.

At first glance you may think of using the UpdatePanel control along with Timer. Though you can achieve
similar results using UpdatePabel and Timer control there are a few limitations. Consider, for example, that
your form is too lengthy and you have placed everything inside an UpdatePanel. Now when UpdatePanel
refreshes the whole data entry form will be refreshed and the user will have to wait till it reappears. Also, saving selected fields
for auto save operation will be tedious and may call for a rearrangement of the data entry fields. So it is best to rollout your own
auto saving mechanism.

Software Needed

In order to work through the example that follows you need to have ASP.NET Framework
4.0 installed on your machine. Though the example is developed using Microsoft Visual
Studio 2010 even Visual Web Developer Express Edition can be used. Additionally,
you need SQL Server 2005 / 2008 database as our data will be stored there.

Creating a Web Site

To begin with, create a new ASP.NET Web Site using Microsoft Visual Studio. Figure
1 shows the "New Web Site" dialog. Give Web Site folder name as AutoSave.

Figure 1

Adding SQL Server Database

Once the web site is ready you need to add a new SQL Server database. If you
have a stand-alone installation of SQL Server along with SQL Sever Management
Studio you can also create a database externally. To add a new database to your
web site locate the App_Data folder in Solution Explorer, right click on it and
choose "Add New Item...". The Add New Item dialog as shown in Figure 2 will be
displayed.

Figure 2

Select "SQL Server database" from the list, give the database the name of your choice and click the Add button. Once the
database is added double click on it in the Solution Explorer so as to open the Server Explorer. Expand the database node, right click
on the Tables node and choose Add New Table. This will open the table definition dialog as shown in Figure 3.

Figure 3

Figure 3 shows a sample table named Article with five columns viz. Id, ArticleTitle, ArticleContent, SubmittedBy and SubmittedOn. Notice the data types of individual columns. Once the Articles table is created proceed to add a WCF
service that works with the data from this table.

The Service class is marked with [ServiceContract] attribute which indicates
that the underlying class is a WCF service. Its Namespace property is set to AutoSaveService indicating that the caller of the service (client side Ajax code
in our case) will see the service class (Service) to be part of AutoSaveService
namespace. You can, of course, give it the name of your choice instead of
AutoSaveService.

You need to transfer data from the web form controls to the WCF service you
just created. One way to do this is to add the required number of parameters to
the service method. A more elegant way is, however, to create a separate class to
carry the data from client to the service. To do this, manually add a new class
in the Service.cs file as shown below:

The above code consists of a class named AutoSaveData that is marked with [DataContract]
attribute. The [DataContract] attribute marks a class as a data contract and
makes it serializable for the sake of data transfer. The AutoSaveData class
consists of three public properties namely ArticleTitle, ArticleContent and
SubmittedBy. All of them are marked with the [DataMember] attribute. The [DataMember]
attribute marks the members for serialization. Now that the AutoSaveData class
is ready let's complete the Service class by adding a method to get the data
in and out of the database.

You will use LINQ to SQL to communicate with the database. Right click on the App_Code folder, select "Add New Item" and choose LINQ to SQL classes (Figure 5). Doing so will add a .dbml file to your web site.

[Figure5.jpg]
Figure 5

Once added drag and drop the Articles table from Server Explorer onto the
design surface of the dbml file. This will automatically create a LINQ to SQL
class named Article as shown in Figure 6.

[Figure6.jpg]
Figure 6

As you can see, the article class has all the properties corresponding to the
columns of the articles table.

The SaveWork method takes a parameter of type AutoSaveData (the class you
created earlier) and is decorated with the [OperationContract] attribute. The [OperationContract]
attribute marks a method as remotely callable. Inside the SaveWork method you
first need to determine if there is any data saved for the same user. If not the
supplied data is inserted into the articles table otherwise the existing record is
updated. Notice that here you are following a simplistic approach by checking merely
the SubmittedBy value. In more realistic case you will have Forms Authentication
enabled for your site and user name along with some extra parameters will be
used while querying the data.

The SaveWork method first creates an instance of the DataClassesDataContext class
(the LINQ to SQL class that gets created when you add a .dbml file). As the name suggests
the DataClassesDataContext class represents a LINQ data context and provides
access to the data. The code then finds out if there is any record matching the SubmittedBy value. This is done using a LINQ query. If the query does not return any record that means there is no data for that user and you insert a new record
otherwise you update the existing record. The SubmitChanges() method of the LINQ
data context saves the changes to the database. Notice that the values to be inserted
or updated are supplied by the AutoSaveData object.

At the end of the SaveWork method a delay is introduced using the Thread.Sleep() method. This is done purely for testing purposes so that you can see the client messages even during local run. Once you are done you should remove
this delay.

Now that you have finished the SaveWork method let's move ahead and create
the Ajax client side component that consumes the WCF service you just created.

Implementing Auto Save Feature Using ASP.NET Ajax and WCF Service

Creating the Ajax Component

The Ajax client side code can be added as a part of <script> tag within the web
form. However, since you are creating a component it is better to keep the code
in a separate file. To do so, add a new JScript file to your web site (Figure 7).

[Figure7.jpg]
Figure 7

In the JScript file you will create an Ajax class named AutoSave. Begin by
placing the namespace declaration as shown below:

Type.registerNamespace("AjaxDemos");

The code above declares the AjaxDemos namespace. The AutoSave class you create
further will be part of this namespace. The following code fragment shows the
constructor of the AutoSave class.

The code calls the initializeBase() method that invokes the base class constructor.
Recollect from our earlier discussion that the Ajax components inherits from Sys.Component base class.
You also need to declare certain private variables (all that
begin with an _ character are private variables for Ajax) to store interval of
auto save operation and to indicate whether the auto save operation is enabled. The
default interval for auto save operation is set to 5000 milliseconds. The serviceCallback and dataCallback parameters are function references. These
functions will be invoked later to construct an instance of Service class and AutoSaveData
class respectively.

Next comes the prototype of the AutoSave class that contains the properties and
methods. The public properties viz. Interval and Enabled
are shown below:

The get_Interval and get_Enabled properties are straightforward and need no
explanation. The set_Interval property sets the _interval variable to a new
value and calls the raisePropertyChanged() method supplying the name of the property
being changed. If the client code has wired an event handler to propertyChanged
event of the Sys.Component class you can process this change if needed. The _StopAutoSave() and
the _StartAutoSave() methods (you will code them in a minute)
simply stop and start the auto save operation so that the new interval comes into effect.
The set_Enabled property simply calls the _StartAutoSave() or _StopAutoSave() methods
depending on the boolean value supplied.

Next the AutoSave class defines a few methods to add event handlers for two
events viz. DataSaving and DataSaved. The DataSaving event will be raised just
before the auto save operation and DataSaved event is raised after the
auto save operation is over. All the AddXXXX and RemoveXXXX methods shown above
make use of events collection provided by the base class Sys.Component and add
or remove event handler using the addHandler() and the removeHandler() method
respectively.

The actual task of raising DataSaving and DataSaved events happens inside
_RaiseDataSavingEvent() and _RaiseDataSavedEvent() methods. These methods simply get a reference to the
handler method and invoke it with two parameters viz. object instance and EventArgs. As you can see the event handler looks similar to
standard server side event handlers.

The _SaveWork() method is important one as it calls the WCF service created
earlier. Inside this method you first turn off the Enabled property so that next
call to _SaveWork() will not fire unless the previous is finished. DataSaving
event is also raised so that client web form can give some visual notification
to the user. The createDelegate()
method essentially creates a pointer to the code you wish to execute. Doing so
preserves the context for the code being called. Notice the use of _serviceCallback
and _dataCallback function references. The first call returns an instance of the WCF
service proxy class whereas the second call returns an instance of AutoSaveData
class filled with textbox values. You then call SaveWork() method
on the WCF service proxy passing it four parameters. The first parameter is the
actual parameter required by the SaveWork() method on the server. The second
parameter is a JavaScript function that gets called when the operation is
successful. The third parameter represents a JavaScript function that gets
called in case of an error. The last parameter is user context and you
pass it as a null since you don't need it in this example. Notice that since the Ajax
calls remote methods asynchronously the return value of the SaveWork() method is not
available immediately.

The _OnSuccess() method is called when the remote service call returns
successfully and receives a parameter that represents the actual return value of
the remote method that was called. Inside this function you just raise the DataSaved
event and enable the auto save operation again. The _OnError() method is called in case of an error while executing the
remote method. You simply display the error message using the get_message() method of
the error object received as a parameter.

The _StartAutoSave() method first creates a delegate that points to the _SaveWork()
method. This is done with the help of the createDelegate() method. The setInterval()
method of JavaScript window object is then called passing this delegate and
interval. The setInterval() method is responsible for invoking the saving operation
after a predefined period of time. Notice the use of the _handle variable to store
the returned integer value of the setInterval() method. This value is needed further
in the _StopAutoSave() method.

The _StopAutoSave() method calls the clearInterval() method of the window
object and clears the previously set interval.

Implementing Auto Save Feature Using ASP.NET Ajax and WCF Service

Creating a Data Entry WebForm

Now that your AutoSave Ajax class is ready let's build a web form that
actually uses this class. Begin by opening the default web form (when you create
a new website in Microsoft Visual Studio 2010 a default web form with a master page gets added for
you. In our example the master page has been removed for the sake of simplicity)
and design it as shown in Figure 8.

[Figure8.jpg]
Figure 8

The web form has a ScriptManager control placed on it. In order to use any
Ajax functionality a web form must have a ScriptManager control. The Label
control placed at the top displays messages before and after auto saving
operation so that the user is aware that the data is automatically getting saved
on the server. The Title, Content and Submitted By textboxes collect the
respective pieces of information. The Submit button performs the saving
operation explicitly.

Once the web form is designed select the ScriptManager control and open its
Properties window. Locate Scripts collection and add a reference to JScript.js
file that contains AutoSave class. This way the ScriptManager knows about your
Ajax class and you can use the class properties and methods on the web form. Figure 9
shows the ScriptReference collection editor dialog.

[Figure9.jpg]
Figure 9

Similarly locate Services collection and add a reference to Service.svc. This
is necessary because in order to call methods of the WCF service (which is on
the server side) Ajax code needs a proxy for it. ScriptManager does this job for
you based on the service references. Figure 10 shows the ServiceReference
collection editor with a reference pointing to Service.svc.

[Figure10.jpg]
Figure 10

Setting the properties as shown above adds the following markup to your web
form:

The Application class from Sys namespace provides access to client components
that are registered with the application. The load event of Application object
is raised when all the registered components are fully constructed and
initialized. The load event handler is shown below:

Inside the load event handler you create an instance of the AutoSave class and
pass two function references. The GetServiceInstance() and GetDataInstance()
functions will be coded in a minute. Two event handlers to handle DataSaving and DataSaved events of
AutoSave class are added using the AddDataSavingEvantHandler() and
AddDataSavedEvantHandler() methods. Its Enabled property is set to true and
Interval property is set to 5000 milliseconds.

The GetServiceInstance() function simply creates an instance of the Service class
from AutoSaveService namespace. The GetDataInstance() then creates an instance of AutoSaveData class and fills its
properties. Notice the use of $get to retrieve textbox values instead of
traditional the getElementById() method of document object.

The OnDataSaving() and OnDataSaved() methods act as event handlers for DataSaving and DataSaved
events of the AutoSave class. They simply display a message to the end user so
that the user is informed about the status of the auto save operation.

The server side Click event handler of Submit button simply creates an
instance of Service class and calls its SaveWork() method.

Testing the Web Form

Now that your coding is complete let's run the web form and see the auto save
operation in action. Run the default web form and fill the textboxes with some
data. Figure 11 and 12 show how the label placed at the top displays the auto
saving related messages.

[Figure11.jpg]
Figure 11

[Figure12.jpg]
Figure 12

Figure 13 shows the data that got saved in the database because of the auto
save operation. Try the functionality by changing the "Submitted By" value.

[Figure13.jpg]
Figure 13

Summary

ASP.NET Ajax component is a non-visual class that inherits from Sys.Component
base class. In this article you learned how Ajax and WCF can be used to implement the
auto save feature in web forms. You first developed a WCF service that talks
with the database to store information. You then consumed this service from
client web form using an Ajax component. Auto saving feature
thus implemented can be very useful for lengthy data entry forms.

Related Articles

About the Author

Bipin Joshi

Bipin Joshi is a blogger and writes about apparently
unrelated topics - Yoga & technology! A former Software Consultant by
profession, Bipin has been programming since 1995 and has been working with the .NET framework ever since its inception. He has authored or co-authored half a dozen books and
numerous articles on .NET technologies. He has also penned a few books on Yoga.
He was a well known technology author, trainer and an active member of Microsoft
developer community before he decided to take a backseat from the mainstream IT
circle and dedicate himself completely to spiritual path. Having embraced Yoga
way of life he now codes for fun and writes on his
blogs. He can also be reached there.