Nov
14
2006
ASP.NET and JQuery - updating templated controls with AJAH
Posted by admin under
Ajax
Continuing our serie on JQuery and ASP.NET we are now gonna create an interface looking like this:

When selecting a filter we want to spawn an Ajax request and update only the table part of the interface:

So far we have used ASHX handlers and returned JSON structures containing business data so to speak - however now we sure would like to have the page generate the pure HTML for the ajax request - just like it generates the HTML for the table if not using ajax at all. Cause in the pages aspx file we have our asp:repeater code defining the table layout (using the same technique as described here).
So the solution? We are gonna set the ajax request to point to the page (aspx) file - and then try to diffrentiate that ajax call from a regular page request - cause if it's ajax we should just return the html the repeater spits out.
First some standard code:
protected DataTable GetData(string sFilter)
{
string sFilterToUse = "";
if (sFilter == "Mr")
... code removed for clarity...
return Microsoft.ApplicationBlocks.Data.SqlHelper.ExecuteDataset(ConfigurationSettings.AppSettings["connstring"],
CommandType.Text, "select * from employees" + sFilterToUse).Tables[0];
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
rptTable.DataSource = GetData(Request["filter"]);
rptTable.DataBind();
...
In the rptTable_ItemDataBound we set the labels etc defined in the template. Just like the original code so far.
Now - lets add the JQuery stuff:
<script type="text/javascript">
$(document).ready(function()
{
$('#Select1').change(function() {
var str = $('#Select1').val();
var sUrl = 'default.aspx?w=callback&filter=' + str;
AjaxGetHTML(sUrl);
});
})
function AjaxGetHTML(sUrl)
{
$.get(sUrl,function(result)
{
$('#repeater1').html( result );
});
}
...
...
</script>
Select filter:
<select id="Select1">
<option selected="selected" value="All">All</option>
<option value="Mr">Mr</option>
<option value="Dr">Dr</option>
<option value="Ms">Ms</option>
<option value="Mrs">Mrs</option>
</select>
...
...
Pretty basic. We add a handler for Select1 change event and from there we create a url string - based on the selected value, however we calso add an extra parameter w=callback.
In other words if the user selects filter "Ms" the url will be
default.aspx?w=callback&filter=Ms
And we call AjaxGetData which retrieves the data from that url and puts it into a div (which is the div containg the repeater). Meaning the repeaters html code will be totally replaced.
So far it seems fine - now lets go back to look at the serverside code - what do we do in the Ajax callback (i.e w=callback?):
This is how Page_Load looks like:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (Request["w"] != null && Request["w"] == "callback")
{
rptTable.DataSource = GetData(Request["filter"]);
}
else
rptTable.DataSource = GetData("");
rptTable.DataBind();
if (Request["w"] != null && Request["w"] == "callback")
{
//Just return the rptTable html...
Response.Cache.SetCacheability(HttpCacheability.NoCache);
string sRet = GetHtml( rptTable );
Response.Write(sRet);
Response.End();
}
}
We create the repeaters datasource as usual and databind it, however when we are inside a callback we call a function GetHtml (which generates the html for the control sent in to it) and just write that back to the client!
The last secret is the GetHtml function:
//Place this function in a helper class instead - but kept in form class for clarity here
public static string GetHtml(Control oCtrl)
{
StringBuilder oBuilder = new StringBuilder();
HtmlTextWriter oWriter = new HtmlTextWriter(new StringWriter(oBuilder));
try
{
oCtrl.RenderControl(oWriter);
}
finally
{
oWriter.Close();
}
return oBuilder.ToString();
}
That code is taken from Nigel Liefrinks article at codeproject
Last 1: About the AJAH in the header - no I have NOT mispelled ajax. Cause this technique is not Asynchronous Javascript And Xml - but rather Asynchronous Javascript And Html.
Last 2: About the strange filtering code I use in GetData(). Not production quality - however I just wanted to avoid the standard comment - "your code is volnerable to sql injection"