Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Improving Maintainability of Legacy Code With a JSON Architecture

5.00/5 (7 votes)
31 May 2012CPOL5 min read 27.2K   76  
This article details how to make a legacy code base more maintainable by utilizing a JSON architecture.

Introduction

Every application at one point is challenged with a re-architecture to a more robust technology. While some are fortunate enough to rewrite their software entirely—updating the core language that the application is built on, most are tasked to do more with less. The approach that we took at Cayen Systems to give our app a face lift included utilizing JQuery with other client side technologies, while still preserving the classic ASP foundation. 

Background 

Our JQuery modernization can be described in two parts: the first is an overhaul of the UI, and the second is a refactoring of how the pages communicate with one another. I will not go into too much detail on how we modernized our code base using jQueryUI, since there are a plethora of available resources that can help a developer utilize this technology. Instead, the focus of this article will be on page architecture using jQuery and JSON with some exposure to our jQueryUI implementation.

As you read this article, if you have any questions about implementation, feel free to reference the demo project. All snippets referenced below can be found in the sandbox archive attached to the article.  

Step 1: Create the JQuery Library File (module.js)

Within your module.js file, start by creating the placeholder for the JSON object. This variable will be global and will be initialized at a later point—to be explained. See the code below:

JavaScript
var jsonData = null

Add code to the JQuery initializer function that will create a div & iframe in preparation for the jQuery dialog. I would like to point out that using iframes in some circles is considered poor practice, an alternative to using an iframe is to use AJAX coupled with dynamic html to populate the div. Since HTML 5 supports iframes, and this particular solution offers more isolation between the module and the implementation, I decided to go with this route instead:

JavaScript
$(function() {
  $('body').append(
    '<div id="divModule" style="padding:0;display:none;">' + 
      '<iframe id="iframeModule" style="width:100%;height:100%;"></iframe>' + 
    '</div>'
  );
});

The openModule function is responsible for setting the JSON object and opening the dialog. In order to make the module’s markup easier to manage, a separate HTML page is created that will house the interface. Once the openModule function fires, the iframe’s location will update to the module.asp page; immediately thereafter the div is converted to a dialog:

JavaScript
function openModule(){
  jsonData = loadModule();
  $('#divModule').dialog({
    height: 225,
    width: 400,
    title: 'Module Title',
    modal: true,
    resizeable: false,
    close: function () {
      closeModule();
    },
    open: function (event, ui) {
      var url = 'Module.asp';
      $('#iframeModule').get(0).src = url;
    }
  });
}

The closeModule function is tasked with destroying the JSON object and closing the dialog. When the closeModule function fires, the iframe’s location is set to a blank page—this is done to prevent a flicker when you reopen the dialog—and the JSON object is set to null:

JavaScript
function closeModule() {
  jsonData = null;
  if($('#divModule').is(':visible')) {
    $('#divModule').dialog('close');
    var url = 'about:blank';
    $('#iframeModule').get(0).src = url;
  }
}

The loadModule function is responsible for receiving the JSON object from the server via AJAX. Despite the dataType being JSON, it is still necessary to eval the response:

JavaScript
function loadModule(){
  var data = '';
  data += 'Action=Load';

  var json = $.ajax({
  	url: 'Module_Ajax.asp',
  	type: 'post',
  	async: false,
  	dataType: 'json',
  	data: data,
  	success: function (data) {
  	}
  }).responseText;
  
  return eval('(' + json + ')');
}

The saveModule function is tasked with pushing the JSON object back to the server via AJAX. JSON.stringify converts the JSON object to a string format that the server can then convert back into a JSON object:

JavaScript
function saveModule() {
  var data = '';
  data += 'Action=Save';
  data += '&JSON=' + JSON.stringify(jsonData);

  return $.ajax({
    url: 'Module_Ajax.asp',
    type: 'post',
    async: false,
    dataType: 'text',
    data: data
  });
}

Step 2: Create the AJAX Page (module_ajax.asp)

Module_ajax.asp has several dependencies. One being json2.js, and the other being JSON_2.0.4.asp. The former allows the server to create JSON objects from strings and the latter allows the server to build JSON objects from another data source. It’s important to note that I’ve chosen to use the session as a construct to retrieve information, however in almost all cases you will want to use a database instead. Please tweak the database access code as necessary:

VBScript
<%@Language="VBScript" CodePage="65001" %>
<%Option Explicit %>
<script language="JScript" runat="server" src='javascript/json2.js'></script>
<!-- #include file="include/JSON_2.0.4.asp" -->
<%
Dim Action

Action = Request("Action")

Select Case Action
  Case "Load" Load()
  Case "Save" Save()
  Case Else Response.Write("Unknown Request")
End Select

The Load function is responsible for creating the server side version of the JSON object, populating that object from a data source, and then converting the object into a string to be consumed by a client side script. Please update the data source from a session to what makes the most sense in your implementation:

VBScript
Sub Load()
  Dim ID
  Dim JSONData

  Set JSONData = jsObject()
  JSONData("firstname") = Session("FirstName")
  JSONData("lastname") = Session("LastName")

  Response.Write(JSONData.jsString())
End Sub

The Save function is responsible for converting a JSON string into a server side JSON object and pushing the object’s information into a data source. Please update the data source from a session to what makes the most sense in your implementation:

VBScript
Sub Save()
  Dim JSONData
	
  Set JSONData = JSON.Parse(Request.Form("JSON"))
	
  Session("FirstName") = JSONData.firstname
  Session("LastName") = JSONData.lastname
End Sub
%>

Step 3: Create the Module UI (module.asp)

The module itself should be relatively simply. Since it does not contain either the load or save functions, in most cases it will consist of little to no server side code. One thing to note, in the example below I chose to directly access the JSON object from the parent. I went with this approach because of its simplicity, however in some cases it might make more sense to move the JSON object between pages via querystring.

Since the module is a separate page isolated in an iframe, it needs to contain all of the javascript resources necessary for it to function. In addition to the typical JQuery resources (jquery.js and jquery-ui.js) we are also using pure.js. This file allows us to map the JSON object to particular fields on the page:

HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Sample Page</title>
<link type="text/css" rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery.ui.all.css" />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.js"></script>
<script type="text/javascript" src="http://beebole.com/pure/wp-content/themes/BeeBole-pure/libs/pure.js"></script>

In order to use directives you need to specify the UI element (using a JQuery selector) and the name of the JSON property. Once your directive is defined, you then call render which binds the JSON object to the UI fields: 

JavaScript
<script type="text/javascript">
$(function () {
  var directive = {
    '#FirstName@value': 'firstname',
    '#LastName@value': 'lastname'
  };
  $('form[name=Main]').render(window.parent.jsonData, directive);
});

The save function needs to map the values back to the JSON object. Unfortunately directives won’t help in this capacity, so to resolve this problem, we just write traditional JavaScript to update the JSON object. When ready just call the saveModule and closeModule functions as needed:

JavaScript
function save() {
  window.parent.jsonData.firstname = $('#FirstName').val();
  window.parent.jsonData.lastname = $('#LastName').val();

  window.parent.saveModule();
  window.parent.closeModule();
}
</script>
</head>

Next step is to create the fields necessary for displaying the data. It’s important to note that this interface will not post. Instead a save function needs to be called which will trigger the AJAX save (as defined in the module.js file):

HTML
<body>
<form name="Main">
<h1>Sample Module</h1><hr />
<label>First Name</label><input type="text" id="FirstName" /><br />
<label>Last Name</label><input type="text" id="LastName" /><br />
<input type="button" value="Save" onclick="save();" />
</form>
</body>
</html>

Step 4: Implement the Module (implementation.asp)

Since the module is self-sufficient, meaning it can work regardless of how it’s implemented, the implementation is extremely simple, just reference the module.js file in addition to any necessary JQuery dependencies and call the openModule function. Voilà, the module is completed:

HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Sample Page</title>
<link rel="Stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery.ui.all.css" type="text/css" />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.js"></script>
<script type="text/javascript" src="javascript/json2.js"></script>
<script type="text/javascript" src="javascript/module.js"></script>
<script type="text/javascript">
	$(function () {
		$("input[name=OpenModule]").click(function () {
			openModule();
		});
	});
</script>
</head>
<body>
<form name="Main" method="post">
<h1>Sample Module Implementation</h1>
<input type="button" name="OpenModule" value="Open Module" />
</form>
</body>
</html>

Points of Interest

The coolest part of this design is the isolation of the legacy code. With the exception of the AJAX page, all the code in this design is written with current industry standards, making it easier for the code to transition to newer technology—such as MVC & Razor. 

History

No changes as of yet.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)