Grafikus C# – Windows Forms tanfolyam › 15.5 lecke Továbbtanulás · 15.5 lecke · web Eddig telepített, asztali programokat készítettél: a kód a felhasználó gépén fut, a felhasználó a saját gépére telepíti. De a mai szoftverek nagy része webalkalmazás: a felhasználó a böngészőben nyitja meg, a program (és az adat) egy szerveren él. A két világ más szemléletet kíván: máshol fut a kód, más a telepítés és a frissítés, más a biztonság, és más a felelősség az adatokért. Ebben a leckében megérted a kliens–szerver modellt és a HTTP alapjait, látod egy kis ASP.NET Core webes szolgáltatás kódját, és megtanulod, mikor melyik megoldás a jó. Ez készíti elő a 15.6 leckét, amelyben a Windows Forms programod egy webes szolgáltatással beszélget.Desktop és webes felületek különbsége

A lecke végére
- összehasonlítod az asztali és a webes alkalmazást több szempont szerint;
- elmagyarázod a kliens–szerver modellt, a HTTP kérés–válasz működését és az állapotmentességet;
- megkülönbözteted a frontendet és a backendet;
- elolvasol egy ASP.NET Core minimal API kódját;
- érted a webes biztonság alapjait (szerveroldali ellenőrzés, HTTPS, hitelesítés, adatvédelem);
- megalapozottan választasz asztali, webes vagy hibrid megoldást.
Mielőtt elkezded
Ehhez a leckéhez a 12. fejezet (rétegek, modell, szolgáltatás), a 13.5 lecke (bevitel-ellenőrzés), a 11. fejezet (async) és a 15.4 lecke (platformok) szükséges. HTML/CSS ismeret előny, de nem feltétel.
Asztali és webes alkalmazás összehasonlítva
| Szempont | Asztali (telepített) | Webes (böngésző) |
|---|---|---|
| Hol fut a kód? | A felhasználó gépén (kliens). | A szerveren (backend), a böngészőben csak a megjelenítés és a JavaScript (frontend). |
| Telepítés | Szükséges (telepítő, ZIP: 14. fejezet), minden gépen. | Nincs: a böngésző megnyitja a címet. |
| Frissítés | Új verziót kell kiadni, a felhasználónak telepítenie (14.6 lecke). | A szerveren frissítesz egyszer, mindenkinek azonnal új. |
| Elérés, offline | Offline is működik; csak azon a gépen érhető el. | Bárhonnan, bármilyen eszközről (internettel); offline csak különleges megoldással. |
| Hardver és rendszer | Teljes hozzáférés (fájlok, nyomtató, USB, hang). | A böngésző korlátai között (biztonsági homokozó). |
| Adat helye | A felhasználó gépén (14.7 lecke). | A szerveren, közös: több felhasználó ugyanazt látja. |
| Több felhasználó | Nehezebb (közös adatbázis, szinkron). | Természetes: ez a szerver feladata. |
| Biztonsági felelősség | A felhasználó gépe és a telepítés biztonsága. | A szerver védelme, hitelesítés, adatvédelem: te üzemelteted. |
| Költség | Egyszeri fejlesztés; nincs szerver. | Szerver és üzemeltetés (hosting), folyamatos költség. |
| Teljesítmény | A gép erőforrásait használja; gyors, helyi. | Hálózati késleltetés; a szerver kapacitása számít. |
| Kinézet és élmény | Natív, gazdag (Windows Forms, WPF). | HTML/CSS/JavaScript (vagy Blazor): rugalmas, a böngészőtől függ. |
async, a JSON, a naplózás és a hibakezelés mind átvihető a webes szerver oldalra: a backend ugyanúgy C# kód.Jósolj!
Egy iskolai nyilvántartásban a tanárok 10 különböző gépről szeretnék ugyanazt az adatbázist használni, és mindenki a legfrissebb adatot lássa. Melyik megoldás illik jobban?
Jóslat ellenőrzése
A webes (vagy kliens–szerver) megoldás: közös adat a szerveren, nincs szétszórt másolat, nincs telepítés minden gépre. Az asztali programban 10 gép 10 külön adatbázist használna, vagy közös fájlmegosztást, amely zárolási és szinkronizálási gondokat okoz (13.6 lecke).
Hogyan működik a web? Kliens, szerver, HTTP
| Lépés | Ki? | Mi történik? |
|---|---|---|
| 1. | Böngésző (kliens) | Kérést küld a szervernek: a metódus az olvasás (GET), a cím az /api/diakok. |
| 2. | Szerver (ASP.NET Core) | Megkeresi, melyik C# kód felel a címért, és lefuttatja. |
| 3. | Szerver és adatbázis | A szerver lekérdezi a diákok adatait az adatbázisból (a 13.6 lecke tárolója). |
| 4. | Szerver | Összeállítja a választ: állapotkód (200: rendben) és a tartalom, általában JSON formátumban. |
| 5. | Böngésző | Megkapja a választ, és megjeleníti (vagy a JavaScript feldolgozza). |
[
{ "id": 1, "nev": "Anna" },
{ "id": 2, "nev": "Béla" }
]GET: olvasás, POST: új adat, PUT: módosítás, DELETE: törlés), útvonala (/api/diakok), fejlécei és (POST-nál) törzse. A válasznak állapotkódja van (200 rendben, 400 hibás kérés, 404 nincs ilyen, 500 szerverhiba)./api/diakok/3) és a HTTP metódusokkal kezeli. Egy API-t nem csak a böngésző, hanem egy Windows Forms program, egy mobilalkalmazás is hívhat (15.6 lecke).Jósolj!
A felhasználó bejelentkezik a webalkalmazásba, majd a következő oldalra lép. A HTTP állapotmentes. Honnan „tudja” a szerver, hogy ő ugyanaz a bejelentkezett felhasználó?
Jóslat ellenőrzése
A bejelentkezés után a szerver egy sütit (vagy tokent) küld, amelyet a böngésző minden további kéréssel visszaküld: ebből azonosítja a felhasználót. Az azonosító titkos és védett kell legyen (HTTPS, biztonságos süti beállítások), különben ellophatják.
Egy kis webes szolgáltatás C#-ban (ASP.NET Core minimal API)
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var diakok = new List<Diak>(); // egyszerűség kedvéért memóriában (élesben adatbázis)
int kovetkezoId = 1;
object zar = new object(); // a szerver egyszerre több kérést is kezel: szálbiztonság (11. fejezet)
// olvasás: a címhez a Get metódus tartozik; a visszaadott lista JSON-ként megy ki
app.MapGet("/api/diakok", () => { lock (zar) { return diakok.ToList(); } });
// új adat: a kérés törzse (JSON) UjDiak objektummá alakul
app.MapPost("/api/diakok", (UjDiak uj) =>
{
if (string.IsNullOrWhiteSpace(uj.Nev) || uj.Nev.Length > 40) // A SZERVER ellenőriz: a kliensnek nem szabad hinni (13.5 lecke)
{
return Results.BadRequest("A név kötelező, legfeljebb 40 karakter."); // 400-as állapotkód
}
lock (zar)
{
Diak d = new Diak { Id = kovetkezoId++, Nev = uj.Nev.Trim() };
diakok.Add(d);
return Results.Created("/api/diakok/" + d.Id, d); // 201-es állapotkód
}
});
// törlés: az útvonal része az azonosító
app.MapDelete("/api/diakok/{id}", (int id) =>
{
lock (zar) { return diakok.RemoveAll(x => x.Id == id) > 0 ? Results.NoContent() : Results.NotFound(); }
});
app.UseDefaultFiles(); // a wwwroot/index.html a kezdőlap
app.UseStaticFiles();
app.Run();
public class Diak { public int Id { get; set; } public string Nev { get; set; } = ""; }
public record UjDiak(string Nev);MapGet, MapPost, MapDelete egy HTTP metódust és egy útvonalat kapcsol egy C# lambdához. A visszaadott érték (lista, objektum) automatikusan JSON válasz lesz: a szerializálást a keretrendszer végzi (a 10. fejezet System.Text.Json ismerete itt is él).Results.BadRequest (400), Created (201), NoContent (204), NotFound (404) a kliensnek mondja meg, mi történt. A jó API pontos állapotkódot és érthető hibaüzenetet ad.lock védi, különben versenyhelyzet keletkezik. Adatbázisnál az adatbázis kezeli a párhuzamosságot, de a gondolat ugyanaz.dotnet run elindítja a szervert egy helyi címen (például https://localhost:5001): böngészővel vagy az Invoke-RestMethod PowerShell paranccsal kipróbálható. A böngésző címsorába beírt cím GET kérést küld.<!doctype html>
<html lang="hu">
<head><meta charset="utf-8"><title>Diáklista</title></head>
<body>
<h1>Diákok</h1>
<input id="nev" placeholder="Név"> <button id="hozzaad">Hozzáad</button>
<ul id="lista"></ul>
<script>
async function betolt() {
const valasz = await fetch('/api/diakok'); // kérés a szerver felé
const diakok = await valasz.json();
const lista = document.getElementById('lista');
lista.textContent = ''; // töröl, majd újraépít
for (const d of diakok) {
const li = document.createElement('li');
li.textContent = d.nev; // textContent: a szöveg NEM értelmeződik HTML-ként (XSS elleni védelem)
lista.appendChild(li);
}
}
document.getElementById('hozzaad').addEventListener('click', async () => {
const valasz = await fetch('/api/diakok', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ nev: document.getElementById('nev').value })
});
if (!valasz.ok) { alert(await valasz.text()); return; }
document.getElementById('nev').value = '';
betolt();
});
betolt();
</script>
</body>
</html>fetch) kéréseket küld az API-nak, és a válaszból felépíti a megjelenítést. A logika és az adat a szerveren van; a frontend csak a felület. Ezt nevezzük kliens–szerver elválasztásnak.Jósolj!
A frontend JavaScript ellenőrzi, hogy a név nem üres, és csak akkor küldi el. A szerver kódja viszont nem ellenőrzi. Mi a gond?
Jóslat ellenőrzése
Az API-t bárki közvetlenül hívhatja (más programmal, a böngésző fejlesztői eszközeivel), a weboldalt megkerülve: a kliensoldali ellenőrzés semmit nem véd. A szerver ellenőrizzen minden bemenetet; a kliensoldali ellenőrzés csak a kényelmet szolgálja (gyors visszajelzés).
Biztonság és felelősség: ami a weben más
| Téma | Mit jelent? | Védekezés |
|---|---|---|
| Bemenet ellenőrzése | Az API-t bárki hívhatja, bármilyen adattal. | Minden bemenetet a szerveren ellenőrizz (13.5 lecke): típus, hossz, tartomány, kötelező mezők. |
| SQL-beszúrás (injekció) | Ha a felhasználói szöveget közvetlenül fűzöd az adatbázis-lekérdezés szövegébe, a felhasználó megváltoztathatja a lekérdezés jelentését. | Paraméteres lekérdezés (13.6 lecke): az adat soha nem válik a lekérdezés részévé. |
| Weboldalba beszúrt kód (XSS) | Ha a felhasználó szövege HTML-ként értelmeződik az oldalon, mások böngészőjében fut le idegen kód. | A szöveget szövegként jelenítsd meg (textContent, a keretrendszerek automatikus kódolása); ne fűzz bemenetet nyers HTML-be. |
| Titkosított csatorna | Titkosítatlan kapcsolaton a jelszó és az adat lehallgatható. | Mindig HTTPS. |
| Hitelesítés és jogosultság | Ki vagy te (bejelentkezés), és mit tehetsz (jogosultság)? | Kész megoldás (ASP.NET Core Identity, külső szolgáltató); soha ne írj saját jelszókezelést; a jelszót nem tárolod szövegesen, csak sózott hash-ként. |
| Titkok kezelése | Jelszavak, API-kulcsok, adatbázis-kapcsolat. | Nem a forráskódban és nem a verziókezelőben (14.7 lecke): környezeti változó, titokkezelő. |
| Adatvédelem | A szerveren a te felelősséged a felhasználók személyes adata (GDPR). | Csak a szükséges adat, tájékoztatás, hozzáférés-korlátozás, törlési lehetőség, biztonságos tárolás. |
| Naplózás | A szerver hibáit és eseményeit te látod egyedül. | Szerveroldali napló (13.7 lecke), személyes adat nélkül; riasztás hibánál. |
Jósolj!
Az API-kulcsot a C# forráskódba írod, és a kódot feltöltöd egy nyilvános tárhelyre. Mi a kockázat?
Jóslat ellenőrzése
A kulcs nyilvánosan olvasható: automatikus programok percek alatt megtalálják a kiszivárgott kulcsokat, és visszaélhetnek velük (költséges hívások, adatlopás). Titkot ne tegyél a kódba; ha kiszivárgott, azonnal cserélni kell, nem elég törölni a kódból (a történetben megmarad).
Mit tegyél ide: a böngészőben a futó diáklista weboldal, mellette a fejlesztői eszközök Network füle a kérésekkel.Javasolt fájlnév: winforms-15-5-web.webp · Alt szöveg: A webes diáklista és a hálózati kérések
Hibakeresés: te vagy a hibadetektív
Mi a baj, és hogyan javítod?
Gondold végig az okot, és csak utána nyisd le a megoldást.
1. 404-es hiba az API hívásakor
A böngésző „nem található” választ kap. Elírt útvonal (Ok és javítás
/api/diak helyett /api/diakok), vagy nincs bejegyezve a MapGet. Ellenőrizd az útvonalat és a metódust (a böngésző címsora mindig GET).
2. 400-as hiba az adat küldésekor
A A törzs nem érvényes JSON, hiányzik a POST hibás kérést jelez.Ok és javítás
Content-Type: application/json fejléc, vagy a mezők neve nem egyezik (nev a UjDiak.Nev-vel). Nézd meg a hálózati kérés törzsét a böngésző fejlesztői eszközében.
3. CORS-hiba a böngészőben
Egy másik címről hívott API-t a böngésző blokkolja. A böngésző alapból megtiltja, hogy egy oldal másik eredetű (cím, port) API-t hívjon. A szerveren engedélyezni kell a CORS-t a megfelelő eredetre (Ok és javítás
builder.Services.AddCors), vagy a frontendet és az API-t ugyanonnan szolgáld ki. Nem „mindenkinek” engedélyezd (biztonság).
4. A szerver egy kérésnél összeomlik
Hibás bemenetnél 500-as hiba jön. A kezelőkód nem ellenőrzi a bemenetet (Ok és javítás
null, üres név), és kivétel keletkezik. Ellenőrizd a bemenetet, és adj 400-as választ; a szerver naplózza a kivételt (13.7 lecke), de a kliensnek ne adj stack trace-t.
5. Két kérés összeakad
Egyszerre két felhasználó adata keveredik, vagy az azonosító duplán fordul elő. Versenyhelyzet a közös adaton: Ok és javítás
lock, szálbiztos gyűjtemény, vagy adatbázis-tranzakció (11. fejezet, 13.6 lecke).
6. Működik helyben, élesben nem
A webalkalmazás a saját gépeden jó, a szerveren hibás. Eltérő környezet: hiányzó beállítás (kapcsolati szöveg, környezeti változó), írási jog, adatbázis, tűzfal, HTTPS tanúsítvány. Naplózás és a hibaoldalak ellenőrzése (14. fejezet gondolata: tiszta környezetben is próbáld ki).Ok és javítás
Mini projekt: a nyilvántartó webes változata
Készítsd el a diáknyilvántartó legegyszerűbb változatát webes szolgáltatásként és weboldalként, majd hasonlítsd össze a korábbi asztali programmal:
- Projekt:
dotnet new web -n DiakWeb(vagy a Visual Studio ASP.NET Core Empty sablonja), majddotnet run: a helyi cím megnyílik a böngészőben. - API: másold be a leckebeli
Program.cs-t (MapGet,MapPost,MapDelete), és egészítsd ki egyPUTvégponttal (a diák nevének módosítása, ugyanazzal az ellenőrzéssel). - Weboldal: hozd létre a
wwwroot/index.htmlfájlt a leckebeli JavaScripttel; egészítsd ki törlés gombbal minden sor mellett. - Szerveroldali ellenőrzés: a név ellenőrzését (kötelező, legfeljebb 40 karakter, nincs duplikátum) tedd egy külön osztályba (a 12. fejezet szerint), amelyet az API hív.
- Próbák PowerShellből: hívd az API-t
Invoke-RestMethodparanccsal: listázás, új diák, üres név (400-as hiba), nem létező azonosító törlése (404), kitörlés. - Böngésző-eszköz: nyisd meg a böngésző fejlesztői eszközét (F12), a Network fülön nézd meg a kéréseket: metódus, cím, állapotkód, válasz törzse.
- Két böngésző, közös adat: nyisd meg az oldalt két böngészőablakban: add hozzá az egyiken a diákot, frissítsd a másikat; ugyanazt látják-e? Ezt az asztali programnál hogyan oldanád meg?
- Összehasonlító táblázat: szempont, Windows Forms nyilvántartó, webes változat: telepítés, frissítés, hol az adat, több felhasználó, bevitel-ellenőrzés helye, offline működés, üzemeltetési teendők, adatvédelmi felelősség.
- Következtetés: 5–6 mondat: melyik megoldást választanád egy 10 fős iskolai munkacsoportnak, és melyiket egy egyszemélyes naplóprogramnak; mit tennél, ha mindkettő kell (hibrid, 15.6 lecke)?
Megoldás megnyitása (próbáld ki előbb önállóan!)
# --- PowerShell: az API kipróbálása (a cím a dotnet run kimenetében látszik) ---
$alap = "https://localhost:5001/api/diakok"
Invoke-RestMethod $alap # lista
Invoke-RestMethod $alap -Method Post -ContentType "application/json" -Body '{"nev":"Anna"}' # új diák (201)
Invoke-RestMethod $alap -Method Post -ContentType "application/json" -Body '{"nev":""}' # üres név: 400-as hiba
Invoke-RestMethod "$alap/999" -Method Delete # nincs ilyen: 404
Invoke-RestMethod "$alap/1" -Method Delete # törlés (204)
// --- C#: PUT végpont a Program.cs-ben ---
app.MapPut("/api/diakok/{id}", (int id, UjDiak uj) =>
{
if (string.IsNullOrWhiteSpace(uj.Nev) || uj.Nev.Length > 40) { return Results.BadRequest("A név kötelező, legfeljebb 40 karakter."); }
lock (zar)
{
Diak d = diakok.FirstOrDefault(x => x.Id == id);
if (d == null) { return Results.NotFound(); }
d.Nev = uj.Nev.Trim();
return Results.Ok(d);
}
});Várt tapasztalat: az üres névre 400-as, a nem létező azonosítóra 404-es hibát kapsz (a PowerShell kivételként jelzi); a két böngészőablak ugyanazt a listát látja (a frissítés után), mert az adat a szerveren van; a webes változatnál a program frissítése a szerveren egyszer történik. A fejlesztői tanúsítvány miatt a PowerShell figyelmeztethet az első https hívásnál (dotnet dev-certs https --trust megbízhatóvá teszi). A pontos port és a viselkedés a gépedtől és a .NET verziótól függ.
Mit tegyél ide: a böngészőben a kész weboldal, és a PowerShell kimenete a próbákról.Javasolt fájlnév: winforms-15-5-kesz.webp · Alt szöveg: A kész webes nyilvántartó és az API-próbák
Három önálló gyakorlófeladat
Egyszerre csak egyet csinálj: tervezd meg, írd meg, futtasd, ellenőrizd, és csak utána nyisd ki a megoldást.
1. Állapotkódok
Milyen állapotkódot adsz: (a) sikeres lekérdezés; (b) új elem létrehozva; (c) hibás bemenet; (d) nem létező elem; (e) váratlan szerverhiba? (a) 200; (b) 201; (c) 400; (d) 404; (e) 500. Az 500-as hibánál a kliensnek általános üzenetet adsz, a részleteket a szerver naplózza.Egy lehetséges megoldás
2. Melyik hová?
Döntsd el, hogy a következő szabályok a szerverre vagy a kliensre kerüljenek: (a) a név nem lehet üres; (b) gyors visszajelzés gépelés közben; (c) a jegy 1 és 5 között van; (d) csak a tanár törölhet. Mind a szerveren érvényesüljön (a), (c), (d): ezek a szabályok és a jogosultság. A (b) a kliens dolga a kényelemért, de a szerver is ellenőriz. A szabály: a kliensoldali ellenőrzés csak kényelmi, a szerveroldali a biztonsági.Egy lehetséges megoldás
3. Hibrid terv
Rajzold le (szavakkal), hogyan beszélne a Windows Forms nyilvántartó a webes szolgáltatással. A Form eseménykezelője egy szolgáltatás-osztályt hív (12.8 lecke), amely Egy lehetséges megoldás
HttpClient-tel kéri az API-t (async, 11. fejezet), a választ JSON-ból objektummá alakítja, és a Form a listát megjeleníti. A hálózati hibát try–catch kezeli (13.6 lecke). A következő lecke ezt építi fel.
Gyakorlótár: 6 további feladat
Három szinten gyakorolhatsz: alap, közepes és kihívás. Csak a próbálkozás után nyisd le a megoldást.
Alap szint
1. Hol fut a kód?
Asztali programban és webalkalmazásban hol fut a logika? Asztali programban a felhasználó gépén; webalkalmazásban a szerveren (a böngészőben csak a megjelenítés és a JavaScript).Megoldás megnyitása
2. Mi a HTTP metódus?
Melyik metódus olvas, melyik hoz létre, melyik töröl?Megoldás megnyitása
GET olvas, POST létrehoz, DELETE töröl (PUT módosít).
Közepes szint
3. Állapotmentes
Mit jelent, hogy a HTTP állapotmentes? A szerver minden kérést önállóan kezel, nem őrzi az előzőt; az állapotot süti vagy token hordozza.Megoldás megnyitása
4. Frontend és backend
Melyik a böngészőben, melyik a szerveren? A frontend (HTML, CSS, JavaScript) a böngészőben, a backend (ASP.NET Core C#) a szerveren fut.Megoldás megnyitása
Kihívás szint
5. Miért szerveroldali ellenőrzés?
Ha a weboldal már ellenőrzi a bemenetet, miért kell a szerveren is? Az API-t bárki közvetlenül hívhatja a weboldal megkerülésével: csak a szerveroldali ellenőrzés véd.Megoldás megnyitása
6. Mikor melyiket?
Egy egyszemélyes, offline napló és egy közös iskolai jelenléti rendszer: melyik asztali, melyik webes? Az egyszemélyes, offline napló asztali (vagy mobil) program; a közös jelenléti rendszer webes (vagy kliens–szerver), mert több felhasználó közös adatát kell kezelni.Megoldás megnyitása
Gyors önellenőrzés
Válaszolj fejben, és csak utána nyisd le a választ. A kliens kérést küld, a szerver választ ad; az adat és a logika jellemzően a szerveren van. A szerver felülete programok számára, címekkel és HTTP metódusokkal. Szöveges adatformátum, amelyben az API az adatot küldi (10. fejezet). Az ASP.NET Core rövid szintaxisa, amelyben egy útvonalhoz egy lambda kezelőt kapcsolsz ( Titkosítja a kapcsolatot, így a jelszó és az adat nem hallgatható le. Nem a kódban: környezeti változóban vagy titokkezelőben. Asztali (vagy mobil) kliens, amely egy webes szolgáltatással (API) tartja a közös adatot.1. Mi a kliens–szerver modell?
2. Mi az API?
3. Mi a JSON?
4. Mi a minimal API?
MapGet, MapPost).5. Miért kell HTTPS?
6. Hol tartod a titkokat?
7. Mi a hibrid megoldás?
Mit tudsz már?
- Összehasonlítod az asztali és a webes alkalmazást (telepítés, frissítés, adat, biztonság, költség).
- Érted a kliens–szerver modellt, a HTTP metódusokat és állapotkódokat, az állapotmentességet.
- Elolvasol egy ASP.NET Core minimal API-t és egy egyszerű weboldalt.
- Ismered a webes biztonság alapjait, és a szerveroldali ellenőrzés szerepét.
Következő lecke: Webszolgáltatások használata grafikus programból
A Windows Forms programod hívja az API-t: HttpClient, JSON, async, hibakezelés.



