To do this, Right click the project in
solution and click “Add New Item”. Select “Generic Hanlder”. I have named it as
LoadCities.ashx. The HttpHanlder will accept StateID as a query string
parameter to fetch the cities from database. Here, I have hard-coded the
cities based on the state id for easy understanding. Next, the cities should be returned back in JSON format from the
HttpHandler. To know more about JSON and JSON format, please visit the JSON site
referenced in JSON section (Move Top) of this article.
To understand better, i will give a
sample JSON data format that should be returned for a stateid.
[{"City":"Chennai","ID":"1"},{"City":"Coimbatore","ID":"2"}]
As I said earlier, JSON format is
simply key- value pairs, separated by commas and enclosed in curly braces.
Thus, each city is enclosed in curly braces. So, in HttpHanlder we need to
construct the data in JSON format and return it back to the caller.
Refer the below code,
<%@ WebHandler Language="C#"
Class="LoadCities" %>
using System;
using System.Web;
using System.Text;
public class LoadCities : IHttpHandler
{
public void ProcessRequest
(HttpContext context) {
string StateID =
context.Request.QueryString["StateID"];
//Contact Database to get th elist
of cities based on StateID
StringBuilder strCities = new
StringBuilder();
if (StateID == "1")
{
strCities.Append("[");
strCities.Append("{");
strCities.Append("\"City\":\"Chennai\",");
strCities.Append("\"ID\":\"1\"");
strCities.Append("},");
strCities.Append("{");
strCities.Append("\"City\":\"Coimbatore\",");
strCities.Append("\"ID\":\"2\"");
strCities.Append("}");
strCities.Append("]");
}
else if (StateID ==
"2")
{
strCities.Append("[");
strCities.Append("{");
strCities.Append("\"City\":\"Bangalore\",");
strCities.Append("\"ID\":\"1\"");
strCities.Append("},");
strCities.Append("{");
strCities.Append("\"City\":\"Belgaum\",");
strCities.Append("\"ID\":\"2\"");
strCities.Append("}");
strCities.Append("]");
}
context.Response.ContentType =
"application/json";
context.Response.ContentEncoding =
Encoding.UTF8;
context.Response.Write(strCities.ToString());
context.Response.End();
}
public bool IsReusable {
get {
return false;
}
}
}
I have hard coded only for 2 states,
you can loop through the result set from database and give back the data in JSON
format.
Calling HttpHanlder from
jQuery
There are some handful of Ajax methods available in jQuery for AJAX
communications. Here, I am going to use getJSON method to get the result back
from HttpHanlder and bind the DropDownList control.
Read my previous article Using
JQuery in ASP.Net AJAX Applications – Part 1.
This will show you how to integrate
jQuery and use Visual Studio intellisense with our project.
We will declare an onchange event for
the parent DropDownList which will make the AJAX call to the server to fetch the
JSON data. Refer the below code,
<script src="_scripts/jquery-1.2.6.js"
type="text/javascript"></script>
<script
language="javascript">
$(document).ready(function()
{
$("#ddlStates").change(function() {
$("#ddlCities").html("");
var StateID =
$("#ddlStates > option[@selected]").attr("value");
if (StateID != 0)
{
$.getJSON('LoadCities.ashx?StateID='
+ StateID, function(cities) {
$.each(cities,
function() {
$("#ddlCities").append($("<option></option>").val(this['ID']).html(this['City']));
});
});
}
});
});
</script>
Update
If you are using jQuery library 1.3.2, @ character in selector expression have to
be removed since the use of @ with the attribute is deprecated. So, change the stateid selection like,
var StateID = $("#ddlStates > option[selected]").attr("value");
The getJSON method will be called for
every state selection except for the value of “select” in parent DropDownList.
When the JSON result is returned it will call the call-back
function(2nd argument of getJSON method) which will populate the
child DropDownList control.
Execute the page and you can see
Cascading DropDownList in action.
So far so good, now when we try to save
the data again or if there is any postback to the server after the above step,
we will get an exception with a message,
Invalid postback or callback argument.
Event validation is enabled using <pages enableEventValidation="true"/> in
configuration or <%@ Page EnableEventValidation="true" %> in a page. For
security purposes, this feature verifies that arguments to postback or callback
events originate from the server control that originally rendered them. If the
data is valid and expected, use the
ClientScriptManager.RegisterForEventValidation method in order to register the
postback or callback data for validation.
What is the reason for the above
exception?
ASP.Net performs a validation on every
postback called EventValidation which records the values, controls at every
render and it will check the data and control that is generating the event or
postback is in the list recorded in the last render. For example, if a dropdown
with values 1, 2, 3 is rendered to the client, for the next postback event if
someone tries to add a fourth option say “4” in the client (using JavaScript)
and post it to the server the validation fails and the runtime will throw an
exception. ASP.Net will predict it as an attack by default since the content are
different and will throw an exception. Since, the child DropDownList is loaded
in client side without a normal postback it is considered as an attack and the
validation will fail. The result is the above exception.
Resolutions
There are several ways to prevent the
above exception. You can see some of the resolution which can be done to prevent
the above exception below.
1. To resolve the above issue, we can disable the enableEventValidation
either in web.config or in page level.
<pages
enableEventValidation="false"/> in Web.Config or,
<%@ Page
EnableEventValidation="false" %> in a page attribute.
2. The risk in above approach is, we are by-passing the security
validation which may result in intruder attacking our system. Alternate way to
resolve the above issue will be using RegisterForEventValidation() Methods in
ClientScriptManager class. Read my article, Using
JavaScript Effectively in ASP.Net 2.0 – PART 2 to know more about it. Refer
the RegisterForEventValidation() Methods section in the article.
3. An Alternate and easiest way will be replacing the child DropDownList
as a HTML select control by setting runat attribute to server. This is the very
easiest way to prevent the above exception. So, the child DropDownList can be
re-written as,
<select
ID="ddlCities" runat="server">
</select>
Download the source code packed with
this article in Download section to see Cascading DropDownList in
action.
To Access the selected value from server side
Response.Write(Request["ddlCities"]);
|