Door gebruik te maken van een server-side techniek kan je de response laten variëren naargelang de gestelde actie door de gebruiker.
Wij focussen ons op het gebruik van Ajax binnen het .Net gebeuren en bekijken hoe we deze krachtige techniek kunnen toepassen in ASP.Net pagina's.
Reeds vanaf .Net 1.1 was het mogelijk om asynchrone gegevenstransfer te combineren met .Net. Je kan hieromtrent veel opzoekingswerk verrichten en proberen om alles handmatig te programmeren. Anderen hebben je dit echter voorgedaan en boekten reeds fantastische resultaten.
Sinds .Net 2.0 heeft Microsoft zelf mogelijkheden toegevoegd om met asynchroon dataverkeer te werken via de zogenaamde Client Callback functionality en het Atlas-project: de Microsoft benaming voor een extra Framework binnen .Net 2.0 met mogelijkheden voor asynchrone datatransfer.
Het gebruik van Ajax binnen het .Net Framework zal ik voortaan Ajax.Net noemen.
Een voorbeeld om Ajax binnen .Net zonder extra hulpklassen uit te voeren vind je bij Codeproject.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<httpHandlers>
<add verb="POST,GET" path="ajaxpro/*.ashx" type="AjaxPro.AjaxHandlerFactory, AjaxPro.2"/>
</httpHandlers>
[...]
</system.web>
</configuration>
protected void Page_Load(object sender, EventArgs e)
{
AjaxPro.Utility.RegisterTypeForAjax(typeof(Bericht));
}
[AjaxPro.AjaxMethod]
public string ToonBericht()
{
return "Bericht van de server";
}
<body>
<form id="form1" runat="server">
<div>
<input id="Button1" type="button" value="button" onclick="toonServerBericht()"/>
</div>
</form>
</body>
<script type="text/javascript">
function toonServerBericht()
{
Bericht.ToonBericht(maakAlert);
}
function maakAlert(bericht){
alert(bericht.value);
}
</script>
protected void Page_Load(object sender, EventArgs e)
{
AjaxPro.Utility.RegisterTypeForAjax(typeof(Bericht));
}
Deze code geeft Ajax.Net de opdracht om de huidige klasse te onderzoeken op Ajax-vriendelijke methoden. Deze methoden dragen een AjaxMethod-attribuut.
[AjaxPro.AjaxMethod]
public string ToonBericht()
{
return "Bericht van de server";
}
Elke methode die we voor Ajaxgebruik wensen in te stellen moet het AjaxMethod-attribuut dragen.
Wanneer dit gedaan is moeten we enkel nog de opgegeven klassen en methoden client-side gebruiken in Javascript. Met andere woorden: het Ajax.Net raamwerk zorgt ervoor dat op de client automatisch een objectvariabele ter beschikking is met dezelfde naam als de geregistreerde .Net-klasse! De methoden en eigenschappen uit deze klasse kan je nu zonder meer gebruiken in Javascript.
In ons geval kunnen we dus een Bericht-object aanspreken en hiervan de methode ToonBericht toepassen.
function toonServerBericht()
{
Bericht.ToonBericht(maakAlert);
}
Concreet roepen we hier voor een Bericht-object de parameterloze functie ToonBericht aan en geven het ontvangen resultaat door aan de functie maakAlert.
Hier zien we het asynchrone karakter van Ajax.Net: pas als het resultaat binnen is zal de functie maakAlert worden uitgevoerd! Ondertussen kan de gebruiker gewoon blijven doorwerken.
function maakAlert(bericht){
alert(bericht.value);
}
We vangen het resultaat op in de variabele bericht.
Voor deze toepassing maken we gebruik van de spionshop-database
We zullen twee DropDownLists op het scherm brengen. De eerst DropDownList bevat de namen van de categorieën uit de tabel categorie van de database.
Maak je een keuze in deze DropDownList, dan verschijnen de artikels uit deze categorie in de tweede lijst. Deze lijst wordt asynchroon gevuld: de items worden opgevraagd uit de database op het ogenblik dat de gebruiker een keuze maakt.
We zullen zorgen voor een gescheiden presentatielaag (Presentation Layer) en datalaag (Data Access Layer).
<?xml version="1.0"?> <configuration> <appSettings/> <connectionStrings> <add name="SpionshopData" providerName="System.Data.SqlClient" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|Spionshop.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True"/> </connectionStrings> <system.web> <httpHandlers> <add verb="POST,GET" path="ajaxpro/*.ashx" type="AjaxPro.AjaxHandlerFactory, AjaxPro.2"/> </httpHandlers> ... </system.web> </configuration>
De Connectiestring voor de databasetoegang wordt dus vermeld in de Web.config-file in de sectie ConnectionStrings. De aanduiding |DataDirectory| : de datamap van het huidige project. Je zal deze connectiestring moeten aanpassen wanneer je met een andere databaseserver werkt dan SQL 2005 Server Express.
We voegen de Ajax-lijn toe aan Web.config zodat Ajax-request correct worden opgevangen.
CREATE PROCEDURE Categorieen AS SELECT cat_id, categorie FROM categorie ORDER BY categorie GO CREATE PROCEDURE ArtikelUitCategorie @CatID smallint AS SELECT artikel_id, artikel, omschrijving, verkoopprijs FROM artikel WHERE cat_id = @CatID ORDER BY artikel
... using System.Data.SqlClient; public static class DAL { public static DataTable GetCategorie() { SqlConnection myConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["SpionshopData"].ConnectionString); SqlCommand myCommand = new SqlCommand("Categorieen", myConnection); myCommand.CommandType = CommandType.StoredProcedure; myConnection.Open(); SqlDataReader rdr = myCommand.ExecuteReader(CommandBehavior.CloseConnection); DataTable cat = new DataTable(); cat.Load(rdr); return cat; } public static DataTable GetArtikel(int categoryID) { SqlConnection myConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["SpionshopData"].ConnectionString); SqlCommand myCommand = new SqlCommand("ArtikelUitCategorie", myConnection); myCommand.CommandType = CommandType.StoredProcedure; SqlParameter parameterCategoryID = new SqlParameter("@CatID", SqlDbType.Int, 4); parameterCategoryID.Value = categoryID; myCommand.Parameters.Add(parameterCategoryID); myConnection.Open(); SqlDataReader rdr = myCommand.ExecuteReader(CommandBehavior.CloseConnection); DataTable dt = new DataTable(); dt.Load(rdr); return dt; } }
protected void Page_Load(object sender, EventArgs e)
{
AjaxPro.Utility.RegisterTypeForAjax(typeof(DropDownLists));
if (!Page.IsPostBack)
{
DDLcat.DataSource = DAL.GetCategorie();
DDLcat.DataTextField = "categorie";
DDLcat.DataValueField = "cat_Id";
DDLcat.DataBind();
DDLcat.Items.Insert(0, new ListItem("Maak uw keuze...", "0"));
}
}
[AjaxPro.AjaxMethod]
public DataTable GetArtikels(int catid){
return DAL.GetArtikel(catid);
}
De lijst met de categorieën DDLcat wordt gevuld wanneer de pagina voor het eerst wordt geladen.
De methode GetArtikels is gemarkeerd als Ajax-methode en haalt de artikels voor een bepaald categorieid op.
<asp:DropDownList ID="DDLcat" runat="server" onchange="LaadArtikels(this)" BackColor="#FFFFC0" Width="200px">
</asp:DropDownList>
Hier zorgen we voor een client-side actie wanneer de selectie in de categorielijst verandert.
<script type="text/javascript" src="shopartikels.js"></script>
De javascript-functie LaadArtikels plaatsen we in een apart bestand.
function LaadArtikels(DDLcat)
{
//kijken welke categorie gekozen is
var cat_id = DDLcat.options[DDLcat.selectedIndex].value;
//ajax-request doen
//wachten op response en resultaat doorgeven aan LaadArtikels_CallBack
DropDownLists.GetArtikels(cat_id, LaadArtikels_CallBack);
}
//resultaat ajax-request afhandelen
function LaadArtikels_CallBack(response)
{
//kijken of er een fout is opgetreden
if (response.error != null)
{
//fout tonen
alert(response.error);
return;
}
var artikels = response.value;
//kijken of de response iets is wat we verwachten (leeg of een object)
if (artikels == null || typeof(artikels) != "object")
{
return;
}
//referentie naar artikellijst
var DDLart = document.getElementById("DDLart");
//maak artikellijst leeg
DDLart.options.length = 0;
//artikellijst doorlopen
for (var i = 0; i < artikels.Rows.length; ++i)
{
//de kolommen kunnen geadresseerd worden als eigenschappen!
DDLart.options[DDLart.options.length] =
new Option(artikels.Rows[i].artikel, artikels.Rows[i].artikel_id);
}
}
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="DropDownLists.aspx.cs" Inherits="DropDownLists" EnableEventValidation="false"%>
Dit fenomeen heeft natuurlijk zijn oorzaak in het feit dat de artikellijst client-side wordt gevuld, de inhoud is niet bewaard in de ViewState.
Wil je na een PostBack de artikelinfo terugvinden in de lijst, en het juist artikel geslecteerd zien, dan zal je daar wat extra code moeten voor schrijven:
if (!Page.IsPostBack)
{
DDLcat.DataSource = DAL.GetCategorie();
DDLcat.DataTextField = "categorie";
DDLcat.DataValueField = "cat_Id";
DDLcat.DataBind();
DDLcat.Items.Insert(0, new ListItem("Maak uw keuze...", "0"));
}
else //er is een PostBack
{
//Daar DDLart client-side werd aangemaakt, beschikken we server side enkel over de
//meegestuurde Form-info van het geslecteerde artikel, niet meer over de volledige
//lijst van artikels
//Het artikel_id van het geselecteerde artikel kunnen we uit de Form-info halen
string artid = Request.Form[DDLart.UniqueID];
//We halen de geslecteerde categorie op en zoeken de artikels op uit de DB
DDLart.DataSource = DAL.GetArtikel((Convert.ToInt32(DDLcat.SelectedValue)));
DDLart.DataTextField = "Artikel";
DDLart.DataValueField = "Artikel_id";
DDLart.DataBind();
//we zoeken het artikel met het artikel_id zoals door de gerbuiker geselecteerd
DDLart.SelectedIndex =
DDLart.Items.IndexOf(DDLart.Items.FindByValue(artid));
}
| Site | Beschrijving |
|---|---|
| Ajax.Net | Home van Ajax.Net, het Framewerk van Michael Schwarz |
| Code-magazine | Uitgebreid artikel, waarin stap voor stap een 3-tier toepassing gebouwd wordt |
| Codersource.net | Artikel bij codersource.net: basis, dataset, custom object |
| MSDN | MSDN artikel over Ajax.Net, gebruikt hier en daar achterhaalde technieken |
| Developerfusion | Artikel basisgebruik bij developerfusion |
| Meer tutorials: |
| leer ook: | html | | xhtml | | css | | asp | | asp.net | | c# | | ado.net | | linq | | ajax | | java | | javascript |