loader
Foto

ASP.NET Core MVC projekt készítése .NET Core 3.1 keretkörnyezetben

Ebben a cikkben elkészítünk nulláról egy ASP.NET Core MVC projektet. Egy kitalált IoT alkalmazás által küldött adatokat fogunk megjeleníteni MVC alkalmazás segítségével. Célünk az, hogy az MVC projekt ismertetése során megismerjük a C.R.U.D. műveletek alkalmazását, ezért implementáljuk a Create-et, a Delete-et, sőt, még az Edit-et is, noha az IoT alkalmazásnál a cél az adatok fogadása a felhőben, és ezeknek az eltárolása. A szerkesztés (és a létrehozás) nem lenne része egy valós IoT alkalmazásnak.

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).

kep
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).

kep
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).

kep
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).

kep
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.

kep
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).

kep
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).

kep
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.

kep
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).

kep
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).

kep
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.

kep
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).

kep
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).

kep
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.

kep
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).

kep
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.



Egyéb cikkek

Mappa

További cikkeink ebben a témakörben

Régebbi cikkeink

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. . . .

aaa. . . .