Summary
In this article I will explore using a web service to deliver HTML markup content to an HTML aware client using the XML HTTP request object from JavaScript code. In this specific case, I am using a .Net web service to serve the HTML markup and an HTML page to consume it. This same approach can easily be adapted to use other frameworks; for example I could have used an Apache Server to serve the HTML from a PHP page and then used an excel client application to consume it.
Introduction
For this article, .Net Web User Controls will be used to format the HTML and a web service will be used to call the control render method and stream this HTML down to the browser. One Web User Control will contain a GridView control while another Web User Control will provide the dialog box to insert a record into the grid. Finally there will be an exposed method in the Web Service to accept the data to be used for the new row. This method will accept a serialized JavaScript Json object which will contain the row values. The libraries in the example program for handling the Json object in the client browser and for the server were downloaded from the internet and are part of the public domain.
The code in this article is not production ready. It is merely used to prove that this approach is viable and that it is not too difficult to implement. The code functions properly in Firefox 2.0, IE 7.0, and Opera 9.23 but will likely not work correctly in other browser versions. This is mostly due to the fact that different browsers expose the XML HTTP request object differently.
Using the approach presented will likely increase the initial development time for a UI feature over more standard methods. What it should do, however, is provide more separation between the client that is being used to view the HTML and the server or type of server that is being used to generate the HTML. This allows UI elements to be more easily shared between multiple applications. For example, if you created a UI feature to enter Pay pal information then you could use this same UI feature in any number of web applications regardless of whether these web pages reside on a Windows or UNIX server.
Download Code
All of the code used for this example is in the downloadable AjaxWebService project and was created using Visual Web Developer 2005. It has been developed to run in file mode. Set the Ajaxed.html page as the start page when you run it.
Implementation
Server Code
The GridView.ascx control is pretty simple. You will find a GridView on the page bound to a Dataset; nothing at all unique. The webservice is called GetWebControl.asmx. The specific method used to expose the functionality, provided by GridView.ascx to the client, is called "GetMyWebControl" and is shown below:
public string GetMyWebControl(string param)
{
Page lPage = new Page();
// create an instance of the desired control
Control lControl = lPage.LoadControl(param);
// create a HTMLTextWriter object to write the HTML generated by the above
control
StringBuilder lStringBuilder = new StringBuilder();
StringWriter lStringWriter = new StringWriter(lStringBuilder);
HTMLTextWriter lHTMLTextWriter = new HTMLTextWriter(lStringWriter);
//the control must be in a web page to provide the databinding
lPage.Controls.Add(lControl);
lControl.DataBind();
lPage.RenderControl(HTMLTextWriter);
// return it to the HTML client
return lStringBuilder.ToString();
}
The only other method in the web service adds a row to the dataset and is pretty straight forward. It accepts a serialized Json JavaScript object as a parameter and then immediately converts this object to a small custom .Net Contact object so that the values can more easily be accessed.
/// <summary>
/// Insert a data row in the dataset
/// </summary>
/// <param name="param"></param>
[WebMethod]
public void InsertDataRow(string param)
{
DataSet lDataSet = new DataSet();
Contact lContact= Newtonsoft.Json .JavaScriptConvert.DeserializeObject
<Contact>(param);
lDataSet.ReadXml(System.Web.HttpContext.Current.Server.MapPath
(@"App_Data/CustomerData.xml");
DataRow lDataRow = lDataSet.Tables[0].NewRow();
lDataRow["CompanyName"] = lContact.CompanyName;
lDataRow["ContactName"] = lContact.ContactName;
lDataRow["ContactTitle"] = lContact.ContactTitle;
lDataSet.Tables[0].Rows.Add(lDataRow);
DataSet.WriteXml(System.Web.HttpContext.Current.Server.MapPath
(@"App_Data/CustomerData.xml");
}
There is one other simple Web User control used for formatting the HTML for the insert form that is displayed on the client. It is called InsertData.ascx and will be delivered to the client using the same "GetMyWebControl" method as described above.
Client Code
The HTML page used to consume the web service is called Ajaxed.htm. The code in the HTML file is pretty minimal. There is a method called "SendRequest" that is used to create an XML HTTP request object and then used to call the web services methods. The GridView is loaded in the page when the page is rendered by calling the "LoadGridView()" method. The ShowInsertForm() method is used to display the "Insert Dialog" It makes a call to the web service to get the "InsertData.ascx" control HTML. Finally there is an "InsertRow()" method to serialize the input form data into a Json string and call the web services "InsertDataRow()" method. There are also a few empty HTML DIVs that will act as containers for the HTML retrieved from the server and some css classes to provide positioning for these DIVs.
Conclusion
This is certainly more work than creating a .net web form and adding a couple Ajax Update panels to it but it does allow the HTML content to be consumed by a variety of different clients and allows UI web elements to more easily be shared between several applications. Please add a comment if your organization is currently using a similar approach as is described in the article. As I was developing the code I was not able to find much in Google which surprised me so I thought I did write an article to stimulate discussion.