Az ASP .NET programozási nyelv

Komponensek

Egy ASP .NET alapú oldal több komponensből épülhet fel, melyekből egy vagy több el is hagyható. Lényegében az oldalunk állhat csupán HTML oldalakból, de ennek semmi értelme, hiszen pontosan azért választunk valamilyen web alkalmazás fejlesztő környezetet, mert oldalunkat dinamikus tartalommal akarjuk kiegészíteni és ezt a lehető legkényelmesebben akarjuk megtenni.

Egy igazi ASP .NET alkalmazás egy vagy több .aspx kiterjesztésű file -ból, valamint az ezekhez tartozó forrásállományokból áll. Az ASPX file nagyrészt az oldalunk formai megjelenésért felel. Tartalmazhat HTML tag -eket, ASP tag -eket, illetve szinte bármilyen kliens oldali kódot (például JavaScript -et). Ha Visual Studio 2005 -el egy új ASP .NET projektet készítünk, kapunk egy aspx oldat illetve a hozzá tartozó forráskódot tartalmazó állományt melynek nyelve (szinte) tetszőleges lehet. A használni kívánt nyelvet a projekt készítésekor kell kiválasztanunk, természetesen a .NET szemléletének megfelelően később bármely más nyelven is írhatunk az ASPX oldalainkhoz forrásállományt.

Az ASPX fájl

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!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 runat="server">
 <title>Untitled Page</title>
</head>
<body>
 <form id="form1" runat="server">
 <div>

</div>
 </form>
</body>
</html>

Minden az ASP -nek szóló információt <% -k és %> -k között kell elhelyeznünk. A Page azt mondja az ASP értelmezőnek, hogy egy Web Form -ot tartalmazó oldalról van szó. (Itt szerepelhet más is, arról majd később fogok beszélni.) A Language attribútum mondja meg milyen nyelven írhatunk inline kódot az ASPX file -ba, illetve ha tartozik az oldalunkhoz forrás állomány, az milyen programozási nyelven íródott (ebben az esetben ez C#). A CodeFile adja meg, hogy az oldalhoz tartozó forrás melyik file -ban helyezkedik el, az Inherits pedig, hogy azon belül is melyik osztály valósítja meg a Form aktív oldalát.

Az ASP .NET tartalmaz nagyon sok beépített vezérlő elemet, mely megkönnyíti az alkalmazás fejlesztését és támogatja azt a filozófiát, miszerint egy webes alkalmazást úgy fejlesztünk mint egy hagyományos desktop alkalmazást. Ezek lehetnek nagyon egyszerűek, mint például gombok, vagy hyperlinkek, de léteznek komplexebb beépített vezérlőelemek is, mint például a beléptetést támogató vezérlő elemek. Ezeket nem mutatom be részletesen. A Login.aspx mintaalkalmazásunkban a beléptetést végzi. Ehhez egy, az előbb említett elemet használunk:

<%@ Page Language="C#"
AutoEventWireup="true" CodeFile="Login.aspx.cs"
Inherits="Login" %>

<!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 runat="server">
 <title>Untitled Page</title>
 <style type="text/css">
  input {
   border-style: solid;
   border-width: 1px;
  }
 </style>
</head>
<body bgcolor="#ffcc66">

 <form id="form1" runat="server">
  <div style="background-color: #ffcc00; color: #000000; border-style:solid;
  border-color: #000000; border-width: 1px; padding: 5px 5px 5px 5px;">
   <asp:Login ID="Login1" runat="server">
   </asp:Login>
  </div>
 </form>
</body>
</html>

A már említett vezérlő elemet az <asp:Login> … </asp:Login> tag valósítja meg.

A forrásállomány

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class _Default : System.Web.UI.Page
{
 protected void Page_Load(object sender, EventArgs e)
 {
 }
}

A forrásban egyetlen osztályt találunk, melynek csupán egyetlen metódusa van. Az oldal típusának megfelelően ez az osztály a System.Web.UI.Page osztály egy leszármazottja. A Page_Load(object sender, EventArgs e) metódus az oldal betöltődésekor hívódik meg (a Visual Studio 2005 megengedi nekünk, hogy egy osztályunk vagy struktúránk implementációját szétbontsuk akár több file -ba is. Ezt csak akkor tehetjük meg ha az osztálydeklarációnkban szerepel a partial kulcsszó).

A mintaalkalmazásunkban két helyen találkozhatunk nagyobb mennyiségű forráskóddal. Ezek a kvízt, illetve az eredmények megjelenítését megvalósító források. Ezekben az állományokban (restricted/Questions.aspx.cs, restricted/Results.aspx.cs) példát látunk arra is, hogy hogyan tudunk egy oldalt dinamikusan felépíteni:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class Questions : System.Web.UI.Page
{
 protected void Page_Load(object sender, EventArgs e)
 {
  using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["BDCon"].ToString()))
  {
   SqlCommand cmd = cn.CreateCommand();
   cmd.CommandText = "SELECT * FROM kerdesek order by sorszam";
   cn.Open();
   SqlDataReader sdr = cmd.ExecuteReader();
   int cnt = 0;
   while (sdr.Read() && cnt < 14)
   {
    Panel p = new Panel();
    p.ID = sdr["sorszam"].ToString();
    Label question = new Label();
    question.Text = sdr["sorszam"].ToString() +": "+ sdr["kerdes"].ToString();
    p.Controls.Add(question);
    RadioButtonList rbl = new RadioButtonList();
    rbl.ID = sdr["sorszam"].ToString();
    /*add radio buttons*/
    using (SqlConnection cn1 = new SqlConnection(ConfigurationManager.ConnectionStrings["BDCon"].ToString()))
    {
     SqlCommand scmd = cn1.CreateCommand();
     scmd.CommandText = "select * from valaszok where kerdes_szam = " + sdr["sorszam"].ToString();
      cn1.Open();
     SqlDataReader sdr1 = scmd.ExecuteReader();
     while (sdr1.Read())
     {
      rbl.Items.Add(new ListItem(sdr1["valasz"].ToString(), sdr1["sorszam"].ToString()));
     }
    }
    /*end*/
    rbl.ID = "answer" + sdr["sorszam"].ToString();
    p.Controls.Add(rbl);
    qst.Controls.Add(p);
    cnt++;
   }
  }
 }

 protected void Button1_Click(object sender, EventArgs e)
 {
  using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["BDCon"].ToString()))
  {
   String res ="";
   String query = "SELECT helyes FROM valaszok where sorszam=" + ((RadioButtonList)qst.Controls[0].Controls[1]).SelectedValue;
   for (int i = 1; i < 14; i++)
   {
    query += " or sorszam=" + ((RadioButtonList)qst.Controls[i].Controls[1]).SelectedValue;
   }
   query = "SELECT count(r.helyes) from (" + query + ") r where r.helyes = 1";
   SqlCommand cmd = cn.CreateCommand();
   cmd.CommandText = query;
   cn.Open();
   SqlDataReader sdr = cmd.ExecuteReader();
   if (sdr.Read())
   {
    res = sdr[0].ToString();
   }
   using (SqlConnection cn1 = new SqlConnection(ConfigurationManager.ConnectionStrings["BDCon"].ToString()))
   {
    MembershipUser u = Membership.GetUser();
    SqlCommand cmdw = cn1.CreateCommand();
    String username = u.UserName.ToString();
    String date = DateTime.Now.Year.ToString() + "-" + DateTime.Now.Month.ToString() +
     "-" + DateTime.Now.Day.ToString() + " " + DateTime.Now.Hour.ToString() +
     ":" + DateTime.Now.Minute.ToString() + ":" + DateTime.Now.Second.ToString();
    cmdw.CommandText = "INSERT INTO eredmeny(sorszam, nev, idopont, eredmeny) VALUES(1,'"+username+"',
     CAST('"+date+"' AS smalldatetime),"+res+".0)";
    cn1.Open();
    cmdw.ExecuteNonQuery();
   }
  }
  Response.Redirect("Results.aspx");
 }
}

A forrás két metódust tartalmaz. Az első - Page_Load – az oldal betöltődésekor fut le. Ebben állítjuk elő a felhasználói felületet. A felületi elemeket az .aspx fájlban elhelyezett placheholder –höz adjuk hozzá. Amint az látható, az elemeket ugyanúgy hozzuk létre mint egy hagyományos desktop alkalmazásnál:

Label question = new Label();
question.Text = sdr["sorszam"].ToString() +": "+ sdr["kerdes"].ToString();
p.Controls.Add(question);

System.Web.UI.Page

A System.Web.UI.Page osztály egy vezérlő (control), ami a web alkalmazásunk felhasználói felületét valósítja meg. A sender az eseményt kiváltó objektum, az EventArgs pedig az esemény argumentumait tartalmazza.

Master Page

ASP .NET -ben a master page használható arra, hogy az alkalmazásunknak konzisztens kinézetet adjunk, például ha az alkalmazásunkban megjelenítendő web form -jainkat mindig állandó környezettel akarjuk körülvenni, mint például menürendszerrel és állandó információkkal (cégelérhetőség, logo, stb.). Összefoglalva: a master page minden oldalunk - vagy oldalaink egy csoportjának - ugyanazt a kinézetet és felhasználói élményt nyújtja. Ezek után ha a böngészőben megnyitunk egy dokumentumot, a dokumentum tartalma a master page -be ágyazva jelenik meg.

Hogy működik a Master Page?

A master page egy .master kiterjesztésű ASP .NET file (pl.: Layout.master), mely előre definiált formával rendelkezik, ami tartalmazhat statikus szöveget, html elemeket és szerver controllokat is. A master page -et az @Master direktíva azonosítja, ami az @Page direktíva helyett áll (ami az .aspx oldalakat azonosítja). A direktíva a következőképpen nézhet ki:

<%@ Master Language="C#" %>

Az @Master direktíva az @Controll direktíva majdnem minden paraméterét tartalmazhatja, azaz megadhatjuk például az oldalhoz tartozó forrás file -t, illetve megadhatjuk a master page -et reprezentáló osztályt:

<%@ Master Language="C#" CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>

Az @Master direktíva mellett a master page tartalmaz minden felső szintű html elemet amit egy html oldalnak tartalmaznia kell, ezek: html, head és form. Ezek mellett tartalmazhat szerver controllokat, hogy egységes navigációs lehetőséget adjon az oldalainknak. Ezen kívül használhatunk benne bármilyen html, illetve ASP .NET elemet, táblázatokkal (vagy div tag -ekkel) meghatározhatjuk az egységes kinézetet.

Az eddig megemlített statikus elemeken, illetve szerver controllokon kívül - amik minden oldalon megjelennek - a master page tartalmaz egy vagy több ContentPlaceHolder (http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.contentplaceholder(VS.80).aspx - helyfoglaló) controllt is. A placeholder olyan részeket ad meg az oldalon, ahova tartalom töltődhet be. A megjeleníteni kívánt tartalmat más .aspx fájlokban adhatjuk meg:

<%@ Master Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML
1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html >
<head runat="server" >
 <title>A master page címe</title>
</head>
<body>
 <form id="form1" runat="server">
 <table>
 <tr>
 <td><asp:contentplaceholder id="Header" runat="server" /></td>
<td><asp:contentplaceholder id="Main" runat="server" /></td>
 <td><asp:contentplaceholder id="Footer" runat="server" /></td>
 </tr>
 </table>
 </form>
</body>
</html>

A master page -ben elhelyezett placeholder control -ok tartalmát úgy adhatjuk meg, hogy content page -eket hozunk létre, amik lényegében ASP .NET oldalak (.aspx file -ok, melyek tartalmazhatnak hozzá tartozó kódot), melyeket a master page -hez kötünk. Az összekötés a content page @Page direktívájában történik úgy, hogy a MasterPage direktívában megadjuk azt, hogy az adott oldal melyik master page -hez tartozik.

<%@ Page Language="C#" MasterPageFile="~/MasterPages/Layout.master" Title="Content Page"%>

Control

User control (.ascx file) specifikus attribútumokat definiál, amiket az ASP .NET oldal értelmező (page parser) és fordító használ. Ez a direktíva csak ASP .NET user control -okkal használható, azokkal melyek forrása .ascx file -okban van elhelyezve. Néhány, eddig is használt attribútum:

AutoEventWireup Értéke true, vagy false lehet, alapértelmezetten true. Azt adja meg, hogy egy control esemény kezelői az elnevezési konvenciónak megfelelően keresnek -e. Explicit módon is létrehozhatunk eseménykezelőket, ha ezt az attribútumot false -ra állítjuk. Például ha az oldal betöltődését kezelő alapértelmezett metódus (Load_Page) helyett másikat szeretnénk használni, azt a következőképpen lehet megadni:
protected void Page_Load(object sender, EventArgs e) Handles Oldal.Load;
ClassName String, mely megadja annak az osztálynak a nevét, amely futásidőben fordul le a control -hoz. Ez bármely létező osztály lehet, amely a teljes namespace specifikációt is tartalmazhatja. Amennyiben nincs megadva, az osztályt az ASP a control file neve alapján határozza meg. Egy másik oldal, vagy control erre az osztályra az @Reference direktívával hivatkozhat.
CodeBehind Annak a lefordított állománynak a nevét adja meg, amely tartalmazza a control -hoz tartozó osztály implementációját. Ezt az attribútumot az ASP nem használja futás közben. Ez az attribútum csupán az ASP .NET korábbi verzióival való kompatibilitás miatt maradt meg, ASP .NET 2.0 -tól e helyett a CodeFile attribútumot használjuk.
CodeFile Az oldalt reprezentáló (code-behind) osztályt tartalmazó file elérési útvonalát tartalmazza. Ezt az attribútumot az Inherits attribútummal együtt használjuk. Ez az attribútum csak "fordított" control -okkal használható.
Debug Azt jelzi, hogy a control debug szimbólumokkal forduljon -e. Az értéke logikusan true, vagy false. Mivel ez az attribútum erősen befolyásolja a teljesítményt, csak fejlesztési fázisban érdemes true -ra állítani.
Inherits A control -t megvalósító osztály "ősosztályát" adja meg. A UserControl osztály bármely leszármazottja lehet. A CodeFile attribútummal együtt használjuk.

Ennél persze jóval több attribútum létezik. Ezek teljes referenciáját itt: (http://msdn2.microsoft.com/en-us/library/d19c0t4b(VS.80).aspx) megtalálható.