Az MVC (Model-View-Controller) projekt elkészítése előtt hozzuk létre azt az adatbázist, illetve adattáblát, amelyet használni fogunk az ASP.NET MVC projekt elkészítése során. Először az Sql Management Studio alkalmazásával hozzuk létre az "iot" nevű adatbázisunkat (1. ábra).
1. ábra Az "iot" adatbázis elkészítése
Ezután hozzuk létre a "teszt" nevű adattáblát úgy, hogy az "Id" legyen a kulcsmező, illetve ennek az értéke automatikusan növekedjen eggyel (2. ábra). (Korábban már foglalkoztunk adatbázis létrehozásával, itt és itt).
2. ábra A "teszt" adattábla létrehozása
Ezután töltsük fel véletlenszerű adatokkal, akár "manuálisan", vagy akár írhatunk erre .NET keretkörnyezetben egy Console alkalmazást is. Ha a teszt adattáblánk már tartalmaz megjeleníthető adatokat, indítsuk el a Visual Studio-t, és hozzunk létre egy "ASP.NET Core Web" projektet (3. ábra).
3. ábra ASP.NET Core projekt létrehozása
A projekt elkészítésekor meg kell adni a nevét (WebIoTMVC), illetve a mentési helyét is (4. ábra).
4. ábra A projekt nevének megadása
Végül a létrehozandó projektnél meg kell adnunk a webes projekt típusát (API, Razor, MVC, stb), illetve azt, hogy akarunk-e autentikációt alkalmazni (5. ábra). Ennél a példánál nem kerül alkalmazása autentikáció, ezt később a konfigurációs json file-nál látni is fogjuk.
5. ábra A projekt egyéb tulajdonságainak beállításának lehetőségei
A létrejött projekt Solution Explorer-ében megtaláljuk a "Controllers", a "Models" és a "Views" mappákat. A "Controllers" mappában találjuk meg azokat a speciális osztályokat, amelyek tartalmazzák azokat az Action-okat, amelyeknek majd a nézeteiket létre kell hozni a "Views" mappában a "Models"-ben található modellek alapján.
Ebben a mappában hozzunk létre egy Controller osztályt, és válasszuk ki azt az MVC template-et, amely tartalmazza az olvasás/írás Action-öket (6. ábra).
6. ábra Controller osztály létrehozása írás/olvasás műveletekkel
Ezután meg kell adni a létrehozandó Controller osztálynak a nevét. Ennél a lépésnél be kell tartanunk egy nagyon fontos névkonvenciót. Az osztály nevét (iot) ki kell egészítenünk a "Controller" szóval (7. ábra).
7. ábra Az iotController hozzáadása a projekthez
A létrejött "iotController" osztály tartalmazza azokat az Action-öket, amelyek segítségével a különböző adatbázis műveletek (C.R.U.D.) megvalósíthatók. Természetesen ezek az Action-ök még "üresek", ezeket nekünk kell majd "feltölteni" C# kódokkal.
A létrejött iotController osztályt látjuk itt:
namespace WebIoTMVC.Controllers
{
public class iotController : Controller
{
// GET: iotController
public ActionResult Index()
{
return View();
}
// GET: iotController/Details/5
public ActionResult Details(int id)
{
return View();
}
// GET: iotController/Create
public ActionResult Create()
{
return View();
}
// POST: iotController/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(IFormCollection collection)
{
try
{
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
// GET: iotController/Edit/5
public ActionResult Edit(int id)
{
return View();
}
// POST: iotController/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int id, IFormCollection collection)
{
try
{
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
// GET: iotController/Delete/5
public ActionResult Delete(int id)
{
return View();
}
// POST: iotController/Delete/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(int id, IFormCollection collection)
{
try
{
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
}
}
Ahhoz, hogy a különböző adatbázis műveleteket implementálni tudjuk az iotController osztályban, létre kell még hoznunk egy olyan modellt, amelyet alkalmazni tudunk a C.R.U.D. műveletek implementálásakor, illetve a nézetek létrehozásakor. Ezért a hozzunk létre egy "meresModell" nevű osztályt, és módosítsuk a következő példa szerint.
namespace WebIoTMVC.Models
{
public class meresModell
{
public int id { get; set; }
public string hely { get; set; }
public int ertek { get; set; }
public DateTime ido { get; set; }
}
}
Ahhoz, hogy kényelmesen tudjuk majd tesztelni az MVC alkalmazásunkat, írjuk át a "Startup.cs" file-ban a "Home"-t "iot"-re (8. ábra). Ezáltal, amikor elindítjuk debug módban az MVC projektet, akkor nem kell nekünk az URL-ben beírni az "iot"-t, mert default-ból ennek a controllernek az "Index" action-jének a View nézetét fogjuk majd látni, amikor elindítjuk az alkalmazásunkat.
8. ábra A "Home" controller átírása "iot"-re
Sql parancsokat fogunk majd írni a C.R.U.D. műveletek implementálásakor, ehhez viszont meg kell adni az "iot" nevű adatbázisunk elérését, azaz a connection stringet. Ezt megtehetnénk akár az "iotController" (vagy más) osztályban, de elegánsabb az "appsettings.json" file-ban megadni a kérdéses connection string-et. Ezért ennek a file-nak a tartalmát módosítsuk a következő példa szerint (látható, hogy nem szerepel benne más adatbázis elérés, nincs autentikációs adatbázis):
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=.\\SQLEXPRESS; Database=iot;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
Most már elkészültünk a főbb módosításokkal, elkezdhetjük az "iotController" osztályban található Action-ök implementálását. Amikor futtatjuk majd az MVC projektünket, akkor az "Index" Action fog először lefutni. Ezért ennek az action-nek az implementálásával kell tehát kezdenünk. Hozzuk létre először ennek az osztálynak a konstruktorát, illetve példányosítsuk a "List" osztályt, azaz, egy listát hozunk létre. Erre azért van szükségünk, mert a "teszt" adattáblában található rekordokban lévő adatokat soronként fogjuk eltárolni ebben a listában. A lista típusa a korábban létrehozott "meresModell".
public IConfiguration Configuration { get; }
List<meresModell> lista;
string connectionString = null;
public iotController(IConfiguration configuration)
{
Configuration = configuration;
lista = new List<meresModell>();
connectionString = Configuration["ConnectionStrings:DefaultConnection"];
}
// GET: iotController
public ActionResult Index()
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string sql = "Select * from teszt";
SqlCommand command = new SqlCommand(sql, connection);
using (SqlDataReader dataReader = command.ExecuteReader())
{
while (dataReader.Read())
{
meresModell mm = new meresModell();
mm.id = Convert.ToInt32(dataReader["Id"]);
mm.hely = Convert.ToString(dataReader["Hely"]);
mm.ertek = Convert.ToInt32(dataReader["Ertek"]);
mm.ido = Convert.ToDateTime(dataReader["Datum"]);
lista.Add(mm);
}
}
connection.Close();
}
return View(lista);
}
Az Index actionben az első using blokkban felépítjük az adatbázissal a kapcsolatot, illetve egy olyan sql parancsot hozunk létre, amelynek segítségével a "teszt" adattáblából minden rekordot kiolvasunk. A belső using blokknál kiolvassuk egyesével a rekordokat, amelynek az értékeit hozzáadjuk a listához. Ezt a listát adjuk vissza az action végén a View-ban.
Ahhoz, hogy a listát meg tudjuk jeleníteni, kell a View nézet, amely még nincs kész. Álljunk rá egérrel az action nevére (Index), majd az egér jobb gombjával adjuk hozzá a projekthez a nézetet (9. ábra).
9. ábra Nézet hozzáadása az actionhöz
Olyan nézetet válasszunk ki, amely nem üres, ezért a "Razor View"-t válasszuk ki (10. ábra).
10. ábra Razor View kiválasztása
A következő lépésnél (11. ábra) tudjuk megadni azt, hogy ehhez az actionhoz milyen "kinézet" társuljon. Lehet listás nézet, de akár üres is. Tekintettel arra, hogy listaként szeretnénk megjeleníteni az összes kilvasott rekordot, ezért a "List"-et válasszuk ki, és ehhez adjuk meg a felhasználandó modellt is, azaz a "meresModell"-t.
11. ábra A nézet és a modell megadása
Ezután a "Views" mappában létrejön az "iot" almappa, benne az Index.cshtml file, amely a nézetért felel. A legenerált file a következő:
@model IEnumerable<WebIoTMVC.Models.meresModell>
@{
ViewData["Title"] = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.id)
</th>
<th>
@Html.DisplayNameFor(model => model.hely)
</th>
<th>
@Html.DisplayNameFor(model => model.ertek)
</th>
<th>
@Html.DisplayNameFor(model => model.ido)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.id)
</td>
<td>
@Html.DisplayFor(modelItem => item.hely)
</td>
<td>
@Html.DisplayFor(modelItem => item.ertek)
</td>
<td>
@Html.DisplayFor(modelItem => item.ido)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
@Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
@Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</tbody>
</table>
Látható a legenerált kódban, hogy a rekordokat táblázatos megjelenítésben fogjuk ábrázolni, illetve kapunk egy sablont a file végén, amely a szerkesztésért, a részletes megjelenítésért, illetve az adott rekord törléséért felel. Természetesen ezeket a háttérkódokat is meg kell írnunk C# nyelven, de a megjelenítés (linkek) már megtalálhatók a legenerált nézetben.
Ugyanakkor a moellünkben nincs "PrimaryKey", ezért a kommentjelek kitörlése után ezt a nevet írjuk át "id"-re (12. ábra).
12. ábra Módosított linkek a legenerált nézetben
Ezután készítsük el a "Details" action háttérkódját, ehhez másoljuk be a következő kódot az iotController osztályba:
public ActionResult Details(int id)
{
meresModell mm = new meresModell();
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string sql = "Select * from teszt Where Id = '" + id + "' ";
SqlCommand command = new SqlCommand(sql, connection);
using (SqlDataReader dataReader = command.ExecuteReader())
{
while (dataReader.Read())
{
mm.id = Convert.ToInt32(dataReader["Id"]);
mm.hely = Convert.ToString(dataReader["Hely"]);
mm.ertek = Convert.ToInt32(dataReader["Ertek"]);
mm.ido = Convert.ToDateTime(dataReader["Datum"]);
}
}
connection.Close();
}
return View(mm);
}
A Details-nél már nem listaként adjuk vissza az eredményt, hanem modellként, mert csak egy rekord lehet az eredmény (Id kulcsmező a táblában). Generáljuk le ennek az action-nek is a nézetét az előbbi módszer alapján, és a következő kódot kapjuk.
@model WebIoTMVC.Models.meresModell
@{
ViewData["Title"] = "Details";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Details</h1>
<div>
<h4>meresModell</h4>
<hr />
<dl class="row">
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.id)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.id)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.hely)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.hely)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.ertek)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.ertek)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.ido)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.ido)
</dd>
</dl>
</div>
<div>
@Html.ActionLink("Edit", "Edit", new { /* id = Model.PrimaryKey */ }) |
<a asp-action="Index">Back to List</a>
</div>
Ezután készítsük el a "Create" action C# kódját. Vegyük észre, hogy két "Create" action van az iotController osztályban. A "Get" Create azért felel, hogy amikor a "create" linkre kattintunk, akkor a Get kérés ehhez az actionhoz érkezik. Amikor azonban rákattintunk majd a "Submit" nyomógombra a Create nézetben, akkor egy Post keletkezik, amelyet az iotController osztályban lévő [HttpPost] attribútummal rendelkező "Create" action kezeli le.
A "Get" Create-hez nem tartozik módosított C# kód, hiszen csak a nézetet kell a böngészőben megjeleníteni, itt tehát adatbázis művelet nem kerül végrehajtásra.
// GET: iotController/Create
public ActionResult Create()
{
return View();
}
// POST: iotController/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(meresModell mm)
{
if (ModelState.IsValid)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string sql = "Insert Into teszt (Hely, Ertek, Datum) Values " +
"('" + mm.hely + "','" + mm.ertek + "','" + mm.ido.ToString("MM/dd/yyyy") + "')";
using (SqlCommand command = new SqlCommand(sql, connection))
{
command.CommandType = CommandType.Text;
command.ExecuteNonQuery();
connection.Close();
}
}
return RedirectToAction(nameof(Index));
}
else
{
return View();
}
}
A [HttpPost] attribútummal rendelkező Create action akkor kerül végrehajtásra, amikor rákattintunk a nyomógombra, azaz, el kell mentenünk az új rekordot a "teszt" adattáblába. Ehhez az kell, hogy érvényes adatok legyenek megadva a nézetben.
Generláljuk le a Create-hez tartozó nézetet (13. ábra).
13. ábra A Create nézet legenerálása a meresModell alapján
Most hozzuk létre a szerkesztés menüponthoz tartozó hátérkódokat. Amikor az "edit" linkre kattintunk, akkkor a Get kérésnél már meg kell jeleníteni a szerkesztendő adatokat, ezért tehát ez az action nem lehet üres, mint a Create-nél. Amikor a Get kérést szolgáljuk ki, akkor átadásra kerül az "id" értéke, amelyet az sql parancsnak adunk át. Ezzel adjuk meg a lekérendő rekordnak a sorszámát.
A [HttpPost] attribútummal rendelkező Edit action módosítja majd az adott rekord értékét az adattáblában.
// GET: iotController/Edit/5
public ActionResult Edit(int id)
{
meresModell mm = new meresModell();
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string sql = "Select * from teszt Where Id = '" + id + "' ";
SqlCommand command = new SqlCommand(sql, connection);
using (SqlDataReader dataReader = command.ExecuteReader())
{
while (dataReader.Read())
{
mm.id = Convert.ToInt32(dataReader["Id"]);
mm.hely = Convert.ToString(dataReader["Hely"]);
mm.ertek = Convert.ToInt32(dataReader["Ertek"]);
mm.ido = Convert.ToDateTime(dataReader["Datum"]);
}
}
connection.Close();
}
return View(mm);
}
// POST: iotController/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int id, meresModell mm)
{
if (ModelState.IsValid)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
string sql = "Update teszt set Hely='" + mm.hely + "', " +
"Ertek='" + mm.ertek + "', " +
"Datum='" + mm.ido.ToString("MM/dd/yyyy") +
"' Where Id='" + id + "'";
using (SqlCommand command = new SqlCommand(sql, connection))
{
command.CommandType = CommandType.Text;
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
}
return RedirectToAction(nameof(Index));
}
else
return View();
}
Hozzuk létre most az Edit actionhoz tartozó nézetet a meresModell alapján (15. ábra). Ez a nézet azért kell, hogy az iotControllerben található Edit actiont használni tudjuk.
15. ábra Az Edit menüponthoz tartozó nézet létrehozása a meresModell alapján
Végezetül a Delete actiont kell létrehoznunk, ezért másoljuk be az iotController osztályba a következő kódrészletet. Itt is két Delete action van (Get, Post). A Get-es actionben megjelenítjük a törlésre ítélt rekord tartalmát, ezért átadásra kerül a törlendő elem sorszáma. A Post-os Delete actionnél futtatjuk azt az sql parancsot, amely a konkrét törlést valósítja meg.
// GET: iotController/Delete/5
public ActionResult Delete(int id)
{
meresModell mm = new meresModell();
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string sql = "Select * from teszt Where Id = '" + id + "' ";
SqlCommand command = new SqlCommand(sql, connection);
using (SqlDataReader dataReader = command.ExecuteReader())
{
while (dataReader.Read())
{
mm.id = Convert.ToInt32(dataReader["Id"]);
mm.hely = Convert.ToString(dataReader["Hely"]);
mm.ertek = Convert.ToInt32(dataReader["Ertek"]);
mm.ido = Convert.ToDateTime(dataReader["Datum"]);
}
}
connection.Close();
}
return View(mm);
}
// POST: iotController/Delete/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(int id, IFormCollection collection)
{
if (ModelState.IsValid)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
string sql = "Delete from teszt Where Id='" + id + "'";
using (SqlCommand command = new SqlCommand(sql, connection))
{
command.CommandType = CommandType.Text;
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
}
return RedirectToAction(nameof(Index));
}
else
return View();
}
Végezetül hozzuk létre a Delete nézetet is a "View/iot/" mappában (16. ábra).
16. ábra A meresModell alapján legenerálásra kerül a Delete nézet is
Ha megvannak a nézetek (amelyek egy részénél módosítani kell a linkeket (kommentek törlése, PrimayKey átírása Id-re), akkor tudjuk debug módban futtatni a teljes projektünket.
A Microsoft által kínált .NET Core nagy népszerűségnek örvend, hiszen ennek a segítségével már nem csak Microsoft operációs rendszer alatt tudjuk futtatni az alkalmazásainkat, hanem akár Linux rendszeren is. Ehhez azonban a Linux operációs rendszerü. . . .
Ebben a cikkben megnézzük az Ubuntu 20.04-re azoknak a programoknak, szolgáltatásoknak a telepítését, amelyek szükségesek ahhoz, hogy az ASP.NET Core alkalmazások futtathatók legyenek ezen a disztribúción. Ezért telepíteni fogjuk most a keretkörnyeze. . . .
A Microsoft által kínált .NET Core nagy népszerűségnek örvend, hiszen ennek a segítségével már nem csak Microsoft operációs rendszer alatt tudjuk futtatni az alkalmazásainkat, hanem akár Linux rendszeren is. Ehhez azonban a Linux operációs rendszerü. . . .