Skvelý sprievodca, ako zostaviť RESTful API s ASP.NET Core

Podrobný sprievodca, ako implementovať čisté a udržiavateľné rozhrania RESTful API

Foto: Jefferson Santos, zverejnené na Unsplash

Prehľad

RESTful nie je nový pojem. Vzťahuje sa na architektonický štýl, keď webové služby prijímajú a odosielajú údaje z a do klientskych aplikácií. Cieľom týchto aplikácií je centralizovať údaje, ktoré budú používať rôzne klientske aplikácie.

Výber správnych nástrojov na písanie RESTful služieb je rozhodujúci, pretože sa musíme starať o škálovateľnosť, údržbu, dokumentáciu a všetky ďalšie relevantné aspekty. ASP.NET Core nám poskytuje výkonné a ľahko použiteľné API, ktoré je skvelé na dosiahnutie týchto cieľov.

V tomto článku vám ukážem, ako napísať dobre štruktúrované rozhranie RESTful API pre „takmer“ scenár reálneho sveta pomocou rámca ASP.NET Core. Budem podrobne popisovať spoločné vzorce a stratégie na zjednodušenie procesu vývoja.

Ukážem vám tiež, ako integrovať spoločné rámce a knižnice, ako sú Entity Framework Core a AutoMapper, aby ste dosiahli potrebné funkcie.

predpoklady

Očakávam, že budete mať vedomosti o objektovo orientovaných programovacích koncepciách.

Aj keď sa chystám pokryť veľa podrobností o programovacom jazyku C #, odporúčam vám mať základné znalosti o tomto predmete.

Tiež predpokladám, že viete, čo je REST, ako funguje protokol HTTP, čo sú koncové body API a čo je JSON. Tu je skvelý úvodný kurz na túto tému. Poslednou požiadavkou je, aby ste pochopili, ako relačné databázy fungujú.

Ak chcete so mnou kódovať, musíte si nainštalovať .NET Core 2.2 a Postman, nástroj, ktorý budem používať na testovanie API. Na vývoj rozhrania API vám odporúčame použiť editor kódu, napríklad Visual Studio Code. Vyberte editor kódov, ktorý uprednostňujete. Ak vyberiete tento editor kódu, odporúčame vám nainštalovať rozšírenie C #, aby ste mali lepšie zvýraznenie kódu.

Na konci tohto článku nájdete odkaz na úložisko API Githubu, kde môžete skontrolovať konečný výsledok.

Rozsah

Napíšme fiktívne webové rozhranie API pre supermarket. Predstavme si, že musíme implementovať nasledujúci rozsah:

  • Vytvorte RESTful službu, ktorá umožňuje klientskym aplikáciám spravovať katalóg produktov supermarketu. Musí odhaliť koncové body na vytváranie, čítanie, úpravu a vymazanie kategórií výrobkov, ako sú mliečne výrobky a kozmetika, a tiež na správu výrobkov týchto kategórií.
  • Pre kategórie musíme uložiť ich názvy. V prípade výrobkov musíme uchovávať ich názvy, mernú jednotku (napríklad KG pre výrobky merané podľa hmotnosti), množstvo v balení (napríklad 10, ak je výrobok balením sušienok) a ich príslušné kategórie.

Aby som príklad zjednodušil, nebudem sa zaoberať výrobkami na sklade, dodávkou produktov, bezpečnosťou a inými funkciami. Daný rozsah je dostatočný na to, aby vám ukázal, ako ASP.NET Core funguje.

Na vývoj tejto služby v zásade potrebujeme dva koncové body API: jeden na správu kategórií a jeden na správu produktov. Pokiaľ ide o komunikáciu JSON, môžeme myslieť na odpovede takto:

Koncový bod API: / api / categories

Odpoveď JSON (pre žiadosti GET):

{
  [
    {"id": 1, "name": "Ovocie a zelenina"},
    {"id": 2, "name": "Breads"},
    … // Iné kategórie
  ]
}

Koncový bod API: / api / products

Odpoveď JSON (pre žiadosti GET):

{
  [
    {
      "id": 1,
      "name": "Sugar",
      "množstvobalenie": 1,
      „unitOfMeasurement“: „KG“
      "category": {
        "id": 3,
        "name": "Sugar"
      }
    },
    … // Iné produkty
  ]
}

Začnime s písaním žiadosti.

Krok 1 - Vytvorenie API

Najprv musíme vytvoriť štruktúru priečinkov pre webovú službu a potom musíme použiť nástroje .NET CLI na vytvorenie základného webového rozhrania API. Otvorte terminál alebo príkazový riadok (závisí od operačného systému, ktorý používate) a postupne zadajte nasledujúce príkazy:

mkdir src / Supermarket.API
cd src / Supermarket.API
dotnet nový webapi

Prvé dva príkazy jednoducho vytvoria nový adresár pre API a zmenia aktuálne umiestnenie do nového priečinka. Posledný generuje nový projekt podľa šablóny Web API, čo je druh aplikácie, ktorú vyvíjame. Môžete si prečítať viac o týchto príkazoch a iných šablónach projektu, ktoré môžete vygenerovať kontrolou tohto odkazu.

Nový adresár bude mať teraz nasledujúcu štruktúru:

Štruktúra projektu

Prehľad štruktúry

Aplikácia ASP.NET Core pozostáva zo skupiny middlewarov (malé časti aplikácie pripojené k aplikačnému potrubiu, ktoré spracovávajú žiadosti a odpovede) nakonfigurované v triede Startup. Ak ste už predtým pracovali s rámcami ako Express.js, tento koncept nie je pre vás nový.

Po spustení aplikácie sa vyvolá hlavná metóda z triedy Program. Vytvára predvoleného webového hostiteľa pomocou spúšťacej konfigurácie a vystavuje aplikáciu prostredníctvom protokolu HTTP prostredníctvom špecifického portu (štandardne port 5000 pre HTTP a 5001 pre HTTPS).

Prezrite si triedu ValuesController vo vnútri zložky Controllers. Odhaľuje metódy, ktoré sa budú volať, keď API prijme požiadavky prostredníctvom trasy / api / hodnôt.

Nerobte si starosti, ak nerozumiete niektorej časti tohto kódu. Pri vývoji potrebných koncových bodov API sa podrobne opíšem o každom z nich. Zatiaľ túto triedu jednoducho vymažte, pretože ju nebudeme používať.

Krok 2 - Vytvorenie doménových modelov

Budem uplatňovať niektoré koncepčné koncepcie, vďaka ktorým bude aplikácia jednoduchá a ľahko udržiavateľná.

Písanie kódu, ktorý môžete pochopiť a udržiavať sami, nie je také ťažké, ale musíte mať na pamäti, že budete pracovať ako súčasť tímu. Ak sa nestaráte o to, ako píšete kód, výsledkom bude monštrum, ktoré vám a vašim spoluhráčom poskytne bolesti hlavy. Znie to extrémne, však? Ale ver mi, to je pravda.

wtf - meranie kvality kódu pomocou smitty42 je licencované podľa CC-BY-ND 2.0

Začnime tým, že napíšeme vrstvu domény. Táto vrstva bude obsahovať triedy našich modelov, triedy, ktoré budú predstavovať naše produkty a kategórie, ako aj rozhrania úložísk a služieb. Tieto posledné dva pojmy vysvetlím o chvíľu.

Vo vnútri adresára Supermarket.API vytvorte nový priečinok s názvom Domain. V novom priečinku domény vytvorte ďalší priečinok s názvom Modely. Prvým modelom, ktorý musíme pridať do tohto priečinka, je kategória. Spočiatku to bude jednoduchá trieda Plain Old CLR Object (POCO). To znamená, že trieda bude mať len vlastnosti, ktoré popisujú jej základné informácie.

Trieda má ID vlastnosť, na identifikáciu kategórie a Nameproperty. Máme tiež vlastníctvo produktov. Tento posledný bude používať Entity Framework Core, ORM väčšina aplikácií ASP.NET Core, ktoré používajú na pretrvávanie údajov do databázy, na mapovanie vzťahov medzi kategóriami a produktmi. Má zmysel myslieť aj z hľadiska objektovo orientovaného programovania, pretože kategória obsahuje veľa súvisiacich produktov.

Musíme tiež vytvoriť produktový model. Do toho istého priečinka pridajte novú triedu produktu.

Produkt má tiež vlastnosti pre ID a názov. Je to tiež vlastnosť QuantityInPackage, ktorá udáva, koľko jednotiek produktu máme v jednom balení (nezabudnite na príklad sušienky rozsahu aplikácie) a vlastnosť UnitOfMeasurement. Tento typ predstavuje typ výčtu, ktorý predstavuje výpočet možných merných jednotiek. Posledné dve vlastnosti, kategóriaId a kategória, použije ORM na mapovanie vzťahu medzi výrobkami a kategóriami. Označuje, že výrobok má jednu a iba jednu kategóriu.

Definujme poslednú časť našich doménových modelov, výčtu EUnitOfMeasurement.

Konvencie, enumy nemusia začínať „E“ pred ich názvami, ale v niektorých knižniciach a rámcoch nájdete túto predponu ako spôsob na rozlíšenie enumov od rozhraní a tried.

Kód je skutočne jednoduchý. Tu sme definovali iba niekoľko možností pre meracie jednotky, avšak v reálnom systéme supermarketov môžete mať mnoho ďalších meracích jednotiek a možno aj samostatný model.

Všimnite si atribút Popis použitý pri každej možnosti vymenovania. Atribút je spôsob, ako definovať metaúdaje nad triedami, rozhraniami, vlastnosťami a inými komponentmi jazyka C #. V tomto prípade ho použijeme na zjednodušenie odpovedí koncového bodu API produktov, ale zatiaľ sa o to nemusíte starať. Vrátime sa sem neskôr.

Naše základné modely sú pripravené na použitie. Teraz môžeme začať písať koncový bod API, ktorý bude spravovať všetky kategórie.

Krok 3 - Kategórie API

V priečinku Controllers pridajte novú triedu s názvom CategoriesController.

Spravidla sa všetky triedy v tomto priečinku, ktoré končia príponou „Controller“, stanú kontrolermi našej aplikácie. To znamená, že budú vybavovať žiadosti a odpovede. Túto triedu musíte zdediť z triedy Controller definovanej v mennom priestore Microsoft.AspNetCore.Mvc.

Menný priestor pozostáva zo skupiny súvisiacich tried, rozhraní, výčtov a štruktúr. Môžete to považovať za niečo podobné modulom jazyka Javascript alebo balíčkom z Javy.

Nový kontrolór by mal reagovať prostredníctvom trasy / api / kategórií. Dosiahneme to pridaním atribútu Route nad názov triedy, pričom sa podľa konvencie uvedie zástupný symbol, ktorý naznačuje, že trasa by mala používať názov triedy bez prípony radiča.

Začnime vybavovať žiadosti GET. Po prvé, keď niekto požaduje údaje z / api / kategórií cez sloveso GET, API musí vrátiť všetky kategórie. Na tento účel môžeme vytvoriť službu kategórie.

Koncepčne je služba v podstate trieda alebo rozhranie, ktoré definuje metódy na zvládnutie určitej obchodnej logiky. V mnohých rôznych programovacích jazykoch je bežnou praxou vytvárať služby na zvládnutie obchodnej logiky, ako je napríklad autentifikácia a autorizácia, platby, zložité toky údajov, ukladanie do vyrovnávacej pamäte a úlohy, ktoré si vyžadujú určitú interakciu medzi inými službami alebo modelmi.

Pomocou služieb môžeme izolovať spracovanie žiadostí a odpovedí od skutočnej logiky potrebnej na dokončenie úloh.

Služba, ktorú sa chystáme pôvodne vytvoriť, bude definovať jediné správanie alebo metódu: spôsob záznamu. Očakávame, že táto metóda vráti všetky existujúce kategórie v databáze.

Pre zjednodušenie sa v tomto prípade nebudeme zaoberať stránkovaním alebo filtrovaním údajov. V budúcnosti napíšem článok, v ktorom ukážem, ako ľahko zvládnuť tieto funkcie.

Na definovanie očakávaného správania pre niečo v jazyku C # (a v iných objektovo orientovaných jazykoch, ako napríklad Java), definujeme rozhranie. Rozhranie hovorí, ako by malo niečo fungovať, ale nevykonáva skutočnú logiku správania. Logika je implementovaná do tried, ktoré implementujú rozhranie. Ak vám tento koncept nie je jasný, nebojte sa. Po chvíli to pochopíš.

V priečinku Doména vytvorte nový adresár s názvom Služby. Tam pridajte rozhranie s názvom ICategoryService. Podľa konvencie by všetky rozhrania mali začínať na veľké písmeno „I“ v C #. Kód rozhrania definujte nasledovne:

Implementácie metódy ListAsync musia asynchrónne vrátiť výčet kategórií.

Trieda Úloha, ktorá zapuzdruje návrat, označuje asynchrónnosť. Musíme premýšľať asynchrónnou metódou, pretože musíme počkať, kým databáza dokončí nejakú operáciu na vrátenie údajov, a tento proces môže chvíľu trvať. Všimnite si aj príponu „async“. Je to konvencia, ktorá naznačuje, že naša metóda by sa mala vykonávať asynchrónne.

Máme veľa konvencií, však? Osobne sa mi to páči, pretože to umožňuje jednoduché čítanie aplikácií, aj keď ste novým v spoločnosti, ktorá používa technológiu .NET.

„- Ok, toto rozhranie sme definovali, ale nerobí nič. Ako to môže byť užitočné? “

Ak pochádzate z jazyka, ako je Javascript alebo iného jazyka, ktorý nie je výrazne napísaný, tento koncept sa môže zdať čudný.

Rozhrania nám umožňujú vytrhnúť požadované správanie zo skutočnej implementácie. Pomocou mechanizmu známeho ako injekcia závislosti môžeme implementovať tieto rozhrania a izolovať ich od ostatných komponentov.

V zásade, keď používate závislosť injekcie, definujete niektoré správanie pomocou rozhrania. Potom vytvoríte triedu, ktorá implementuje rozhranie. Nakoniec prepojíte odkazy z rozhrania s triedou, ktorú ste vytvorili.

„- Znie to naozaj mätúce. Nemôžeme jednoducho vytvoriť triedu, ktorá by pre nás tieto veci robila? “

Pokračujme vo vykonávaní nášho rozhrania API a pochopíte, prečo používať tento prístup.

Zmeňte kód ovládača kategórií takto:

Definovala som funkciu konštruktora pre náš radič (konštruktor sa volá, keď sa vytvorí nová inštancia triedy) a dostane inštanciu ICategoryService. To znamená, že inštancia môže byť čokoľvek, čo implementuje servisné rozhranie. Túto inštanciu ukladám do súkromného poľa _categoryService určeného iba na čítanie. Toto pole použijeme na prístup k metódam implementácie našej kategórie služieb.

Mimochodom, predpona podčiarknutia je ďalšou bežnou konvenciou označovania poľa. Tento dohovor, najmä, sa neodporúča v oficiálnom návode na pomenovanie .NET, ale je to veľmi bežný postup ako spôsob, ako sa vyhnúť nutnosti používať kľúčové slovo „toto“ na rozlíšenie polí triedy od miestnych premenných. Osobne si myslím, že je oveľa čistejšie čítať a tento rámec používa veľa rámcov a knižníc.

Pod konštruktorom som definoval metódu, ktorá bude vybavovať žiadosti o / api / kategórie. Atribút HttpGet hovorí ropovodu ASP.NET Core, aby ho používal na vybavovanie požiadaviek GET (tento atribút možno vynechať, ale pre ľahšiu čitateľnosť je lepšie ho napísať).

Táto metóda používa inštanciu služby kategórie na zoznam všetkých kategórií a potom vracia kategórie klientovi. Potrubie rámca spracováva serializáciu údajov do objektu JSON. Typ IEnumerable hovorí rámcu, že chceme vrátiť výpočet kategórií, a typ úlohy, ktorému predchádza kľúčové slovo async, hovorí, že táto metóda by sa mala vykonať asynchrónne. Nakoniec, keď definujeme metódu async, musíme použiť kľúčové slovo čakať na úlohy, ktoré môžu chvíľu trvať.

Ok, definovali sme počiatočnú štruktúru nášho API. Teraz je potrebné skutočne implementovať službu kategórií.

Krok 4 - Implementácia služby kategórií

V koreňovom priečinku API (priečinok Supermarket.API) vytvorte nový s názvom Services. Tu uvedieme všetky implementácie služieb. Do nového priečinka pridajte novú triedu s názvom CategoryService. Zmeňte kód nasledovne:

Je to jednoducho základný kód pre implementáciu rozhrania, ale stále nezvládame žiadnu logiku. Pozrime sa, ako by mala metóda zápisu fungovať.

Potrebujeme prístup do databázy a vrátiť všetky kategórie, potom musíme tieto údaje vrátiť klientovi.

Trieda služby nie je trieda, ktorá by mala spracovávať prístup k údajom. Existuje vzor nazývaný Repository Pattern, ktorý sa používa na správu údajov z databáz.

Pri použití vzoru úložiska definujeme triedy úložísk, ktoré v podstate zapuzdrujú všetku logiku na zvládnutie prístupu k údajom. Tieto úložiská vystavujú metódy na zoznam, vytváranie, úpravy a mazanie objektov daného modelu, rovnakým spôsobom ako môžete manipulovať so zbierkami. Interne tieto metódy hovoria do databázy, aby vykonávali operácie CRUD a izolovali prístup k databáze od zvyšku aplikácie.

Aby sme dostali zoznam objektov, musí naša služba hovoriť s archívom kategórií.

Koncepčne môže služba „hovoriť“ s jedným alebo viacerými archívmi alebo inými službami, aby vykonala operácie.

Môže sa zdať zbytočné vytvoriť novú definíciu pre spracovanie logiky prístupu k dátam, ale po chvíli uvidíte, že izolácia tejto logiky od triedy služieb je skutočne výhodná.

Vytvorme úložisko, ktoré bude zodpovedné za sprostredkovanie databázovej komunikácie ako spôsob pretrvávania kategórií.

Krok 5 - Archív kategórií a vrstva perzistencie

Vo vnútri priečinka Doména vytvorte nový adresár s názvom Repositories. Potom pridajte nové rozhranie s názvom ICategoryRespository. Definujte rozhranie nasledovne:

Počiatočný kód je v podstate identický s kódom servisného rozhrania.

Po definovaní rozhrania sa môžeme vrátiť k servisnej triede a dokončiť implementáciu metódy výpisu, pomocou inštancie ICategoryRepository vrátiť dáta.

Teraz musíme implementovať reálnu logiku úložiska kategórie. Predtým, ako to urobíme, musíme premýšľať o tom, ako sa chystáme pristupovať k databáze.

Mimochodom, stále nemáme databázu!

Ako našu databázu ORM použijeme jadro entity (nazývame ho EF Core pre jednoduchosť). Tento rámec je dodávaný s ASP.NET Core ako jeho predvoleným ORM a vystavuje priateľské API, ktoré nám umožňuje mapovať triedy našich aplikácií do databázových tabuliek.

EF Core nám tiež umožňuje najprv navrhnúť našu aplikáciu a potom vygenerovať databázu podľa toho, čo sme definovali v našom kóde. Táto technika sa nazýva prvý kód. Na vygenerovanie databázy použijeme prístup založený na kóde prvý (v tomto príklade používam databázu v pamäti, ale budete ju môcť ľahko zmeniť na inštanciu servera SQL Server alebo MySQL, napríklad).

V koreňovom priečinku API vytvorte nový adresár s názvom Perzistencia. Tento adresár bude mať všetko, čo potrebujeme na prístup do databázy, napríklad implementácia úložísk.

Vo vnútri nového priečinka vytvorte nový adresár s názvom Kontexty a potom pridajte novú triedu s názvom AppDbContext. Táto trieda musí zdediť DbContext, trieda EF Core, ktorá sa používa na mapovanie vašich modelov do databázových tabuliek. Zmeňte kód nasledujúcim spôsobom:

Konštruktor, ktorý sme do tejto triedy pridali, je zodpovedný za odovzdanie konfigurácie databázy do základnej triedy prostredníctvom injekcie závislosti. O chvíľu uvidíte, ako to funguje.

Teraz musíme vytvoriť dve vlastnosti DbSet. Tieto vlastnosti sú sady (zbierky jedinečných objektov), ​​ktoré mapujú modely do databázových tabuliek.

Tiež musíme zmapovať vlastnosti modelov do príslušných stĺpcov tabuľky a určiť, ktoré vlastnosti sú primárne kľúče, ktoré sú cudzie kľúče, typy stĺpcov atď. To môžeme urobiť prepísaním metódy OnModelCreating pomocou funkcie nazývanej Fluent API to zadajte mapovanie databázy. Zmeňte triedu AppDbContext takto:

Kód je intuitívny.

Určujeme, do ktorých tabuliek sa majú naše modely mapovať. Taktiež nastavujeme primárne kľúče pomocou metódy HasKey, stĺpcov tabuľky, pomocou metódy Property a niektorých obmedzení, ako sú IsRequired, HasMaxLength a ValueGeneratedOnAdd, všetko s výrazmi lambda „plynulo“ (metódy reťazenia).

Pozrite sa na nasledujúci kód:

builder.Entity  ()
       .HasMany (p => p.Produkty)
       .WithOne (p => p.Category)
       .HasForeignKey (p => p.CategoryId);

Tu uvádzame vzťah medzi tabuľkami. Hovoríme, že kategória má veľa produktov a nastavujeme vlastnosti, ktoré budú tento vzťah mapovať (Produkty, z kategórie Kategória a Kategória, z triedy Produkt). Tiež sme nastavili cudzí kľúč (CategoryId).

Ak sa chcete naučiť, ako nakonfigurovať vzťahy medzi dvoma a mnohými pomocou EF Core, a ako ich používať ako celok, prečítajte si tento tutoriál.

Existuje tiež konfigurácia na zaočkovanie údajov pomocou metódy HasData:

builder.Entity  (). HasData
(
  nová kategória {Id = 100, Name = "Ovocie a zelenina"},
  nová kategória {Id = 101, Name = "Mairy"}
);

Tu jednoducho pridáme dve vzorové kategórie v predvolenom nastavení. Je potrebné otestovať náš koncový bod API po jeho dokončení.

Poznámka: Nastavujeme vlastnosti ID ručne, pretože poskytovateľ v pamäti vyžaduje, aby fungoval. Nastavujem identifikátory na veľké čísla, aby nedošlo k kolízii medzi automaticky generovanými identifikátormi a počiatočnými údajmi.
Toto obmedzenie neexistuje v prípade skutočných poskytovateľov relačných databáz, takže ak chcete používať databázu, napríklad SQL Server, nemusíte tieto identifikátory zadávať. Ak chcete tomuto správaniu porozumieť, prečítajte si tento problém Githubu.

Po implementácii triedy kontextu databázy môžeme implementovať archív kategórií. Pridajte do priečinka Persistence nový priečinok s názvom Repositories a potom pridajte novú triedu s názvom BaseRepository.

Táto trieda je iba abstraktnou triedou, ktorú zdedia všetky naše archívy. Abstraktná trieda je trieda, ktorá nemá priame inštancie. Na vytvorenie inštancie musíte vytvoriť priame triedy.

The BaseRepository prijíma inštanciu nášho AppDbContext prostredníctvom injekcie závislosti a odhaľuje chránenú vlastnosť (vlastnosť, ktorú môžu sprístupniť iba podradené triedy) s názvom _context, ktorá umožňuje prístup ku všetkým metódam, ktoré potrebujeme na zvládnutie databázových operácií.

Pridajte novú triedu do rovnakého priečinka s názvom CategoryRepository. Teraz implementujeme logiku úložiska:

Úložisko zdedí databázu BaseRepository a implementuje ICategoryRepository.

Všimnite si, aké jednoduché je implementovať metódu výpisu. Na prístup do tabuľky kategórií používame databázovú množinu a potom voláme metódu rozšírenia ToListAsync, ktorá je zodpovedná za transformáciu výsledku dotazu do kolekcie kategórií.

EF Core prekladá naše volanie metód na dotaz SQL, čo najefektívnejší spôsob. Dotaz sa vykoná, len keď zavoláte metódu, ktorá transformuje vaše údaje do kolekcie, alebo ak použijete metódu na prevzatie konkrétnych údajov.

Teraz máme čistú implementáciu radiča kategórií, služieb a úložiska.

Oddelili sme obavy a vytvorili triedy, ktoré robia iba to, čo majú robiť.

Posledným krokom pred testovaním aplikácie je naviazanie našich rozhraní na príslušné triedy pomocou mechanizmu vstrekovania závislosti jadra ASP.NET Core.

Krok 6 - Konfigurácia injekcie závislosti

Je čas, aby ste konečne pochopili, ako tento koncept funguje.

V koreňovom priečinku aplikácie otvorte triedu Startup. Táto trieda je zodpovedná za konfiguráciu všetkých druhov konfigurácií pri spustení aplikácie.

Metódy ConfigureServices a Configure sa v runtime rámci nazývajú pipeline rámcov, aby nakonfigurovali, ako by mala aplikácia fungovať a ktoré komponenty musí používať.

Prezrite si metódu ConfigureServices. Tu máme iba jeden riadok, ktorý konfiguruje aplikáciu tak, aby používala potrubie MVC, čo v podstate znamená, že aplikácia bude spracovávať žiadosti a odpovede pomocou tried kontrolérov (v zákulisí sa deje viac vecí, ale to je potrebné vedieť) na Teraz).

Na konfiguráciu väzieb závislosti môžeme použiť metódu ConfigureServices, ktorá pristupuje k parametru services. Vyčistite kód triedy odstránením všetkých komentárov a zmeňte kód nasledovne:

Pozrite sa na tento kód:

services.AddDbContext  (options => {
  options.UseInMemoryDatabase ( "supermarket-api-in-memory");
});

Tu konfigurujeme databázový kontext. Hovoríme ASP.NET Core, aby používal náš AppDbContext s implementáciou databázy v pamäti, ktorá je identifikovaná reťazcom odovzdaným ako argument pre našu metódu. Poskytovateľ pamäte sa zvyčajne používa pri písaní integračných testov, ale tu ho používam kvôli jednoduchosti. Týmto spôsobom sa nemusíme pripájať k skutočnej databáze, aby sme mohli testovať aplikáciu.

Konfigurácia týchto liniek interne konfiguruje náš databázový kontext pre závislé vstrekovanie pomocou skrátenej životnosti.

Skrátená životnosť hovorí potrubiu ASP.NET Core, že zakaždým, keď potrebuje vyriešiť triedu, ktorá prijíma inštanciu AppDbContext ako argument konštruktora, mala by použiť rovnakú inštanciu triedy. Ak v pamäti nie je inštancia, potrubie vytvorí novú inštanciu a počas danej požiadavky ju znova použije vo všetkých triedach, ktoré ju potrebujú. Týmto spôsobom nemusíte manuálne vytvárať inštanciu triedy, keď ju potrebujete použiť.

Existujú aj ďalšie celoživotné rozsahy, ktoré si môžete prečítať v oficiálnej dokumentácii.

Technika vstrekovania závislosti nám poskytuje mnoho výhod, napríklad:

  • Opätovné použitie kódu;
  • Lepšia produktivita, pretože keď musíme zmeniť implementáciu, nemusíme sa obťažovať meniť sto miest, kde túto funkciu používate;
  • Aplikáciu môžete ľahko otestovať, pretože to, čo musíme testovať, môžeme izolovať pomocou simulovaných falošných implementácií tried, kde musíme ako argumenty konštruktora odovzdávať rozhrania;
  • Keď trieda potrebuje získať viac závislostí prostredníctvom konštruktora, nemusíte manuálne meniť všetky miesta, kde sa vytvárajú inštancie (to je úžasné!).

Po nakonfigurovaní kontextu databázy tiež zaviažeme našu službu a úložisko k príslušným triedam.

services.AddScoped  ();
services.AddScoped  ();

Aj tu používame obmedzenú životnosť, pretože tieto triedy interne musia používať kontextovú triedu databázy. V tomto prípade má zmysel uviesť rovnaký rozsah pôsobnosti.

Teraz, keď konfigurujeme naše väzby závislosti, musíme urobiť malú zmenu v programovej triede, aby databáza mohla správne vložiť naše počiatočné údaje. Tento krok je potrebný iba pri použití poskytovateľa databázy v pamäti (informácie o tomto probléme nájdete v tomto čísle Github).

Bolo potrebné zmeniť hlavnú metódu, aby sme zaručili, že naša databáza bude „vytvorená“ pri spustení aplikácie, pretože používame poskytovateľa v pamäti. Bez tejto zmeny sa nevytvoria kategórie, ktoré chceme vytvoriť.

Po implementácii všetkých základných funkcií je čas vyskúšať náš koncový bod API.

Krok 7 - Testovanie API kategórií

Otvorte terminál alebo príkazový riadok v koreňovom priečinku API a zadajte nasledujúci príkaz:

dotnet run

Vyššie uvedený príkaz spustí aplikáciu. Konzola bude zobrazovať výstup podobný tomuto:

info: Microsoft.EntityFrameworkCore.Infrastructure [10403]
Entity Framework Core 2.2.0-rtm-35687 inicializované „AppDbContext“ pomocou poskytovateľa „Microsoft.EntityFrameworkCore.InMemory“ s možnosťami: StoreName = supermarket-api-in-memory
info: Microsoft.EntityFrameworkCore.Update [30100]
Uložené 2 entity do pamäte v obchode.
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager [0]
Profil používateľa je k dispozícii. Ako úložisko kľúčov použite kľúč C: \ Users \ evgomes \ AppData \ Local \ ASP.NET \ DataProtection-Keys a šifrovanie kľúčov Windows DPAPI v kľude.
Hostiteľské prostredie: rozvoj
Cesta koreňového obsahu: C: \ Users \ evgomes \ Desktop \ Tutorials \ src \ Supermarket.API
Teraz počúvame na adrese: https: // localhost: 5001
Teraz počúvame na adrese: http: // localhost: 5000
Aplikácia sa začala. Stlačením klávesov Ctrl + C program vypnete.

Môžete vidieť, že program EF Core bol pozvaný na inicializáciu databázy. Posledné riadky ukazujú, na ktorých portoch je aplikácia spustená.

Otvorte prehliadač a prejdite na adresu http: // localhost: 5000 / api / categories (alebo na adresu URL zobrazenú na výstupe z konzoly). Ak vidíte chybu zabezpečenia z dôvodu protokolu HTTPS, jednoducho pridajte výnimku pre aplikáciu.

Prehliadač zobrazí ako výstup nasledujúce údaje JSON:

[
  {
     "id": 100,
     "name": "Ovocie a zelenina",
     "Produkty": []
  },
  {
     "id": 101,
     "name": "Dairy",
     "Produkty": []
  }
]

Tu vidíme údaje, ktoré sme pridali do databázy, keď sme nakonfigurovali databázový kontext. Tento výstup potvrdzuje, že náš kód funguje.

Vytvorili ste koncový bod GET API s naozaj malým počtom riadkov kódu a máte štruktúru kódu, ktorá sa dá v dôsledku architektúry API skutočne ľahko zmeniť.

Teraz je čas ukázať vám, aké ľahké je zmeniť tento kód, keď ho musíte prispôsobiť vzhľadom na obchodné potreby.

Krok 8 - Vytvorenie zdroja kategórie

Ak si pamätáte špecifikáciu koncového bodu API, všimli ste si, že naša skutočná odpoveď JSON má jednu ďalšiu vlastnosť: rad produktov. Pozrite sa na príklad požadovanej odpovede:

{
  [
    {"id": 1, "name": "Ovocie a zelenina"},
    {"id": 2, "name": "Breads"},
    … // Iné kategórie
  ]
}

Produktové pole je prítomné v našej súčasnej odpovedi JSON, pretože náš model kategórie má vlastnosť produkty, ktorú spoločnosť EF Core potrebuje na opravu mapy produktov v danej kategórii.

Nechceme, aby toto vlastníctvo bolo v našej odpovedi, ale nemôžeme zmeniť našu triedu modelu, aby sme toto vlastníctvo vylúčili. Spôsobilo by to, že EF Core vyvoláva chyby, keď sa snažíme spravovať údaje kategórií, a tiež by to narušilo návrh modelu domény, pretože nemá zmysel mať kategóriu produktu, ktorá nemá produkty.

Na vrátenie údajov JSON obsahujúcich iba identifikátory a názvy kategórií supermarketov musíme vytvoriť triedu zdrojov.

Trieda prostriedkov je trieda, ktorá obsahuje iba základné informácie, ktoré sa budú vymieňať medzi klientskými aplikáciami a koncovými bodmi API, spravidla vo forme údajov JSON, aby predstavovali niektoré konkrétne informácie.

Všetky odpovede z koncových bodov API musia vrátiť zdroj.

Je zlou praxou vracať skutočnú reprezentáciu modelu ako odpoveď, pretože môže obsahovať informácie, ktoré klientska aplikácia nepotrebuje alebo nemá povolenie mať (napríklad užívateľský model by mohol vrátiť informácie o užívateľskom hesle) , čo by bol veľký bezpečnostný problém).

Potrebujeme zdroj, ktorý bude reprezentovať iba naše kategórie bez výrobkov.

Teraz, keď viete, čo je to zdroj, poďme ho implementovať. Najskôr zastavte spustenú aplikáciu stlačením klávesov Ctrl + C na príkazovom riadku. V koreňovom priečinku aplikácie vytvorte nový priečinok s názvom Zdroje. Tam pridajte novú triedu s názvom CategoryResource.

Naša zbierka modelov kategórií, ktorú poskytuje naša kategória služieb, musíme zmapovať do zbierky zdrojov kategórie.

Na mapovanie medzi objektmi použijeme knižnicu s názvom AutoMapper. AutoMapper je veľmi populárna knižnica vo svete .NET a používa sa v mnohých komerčných a open source projektoch.

Do príkazového riadka zadajte nasledujúce riadky, aby ste do našej aplikácie pridali aplikáciu AutoMapper:

dotnet add package AutoMapper
dotnet add package AutoMapper.Extensions.Microsoft.DependencyInjection

Ak chcete používať AutoMapper, musíme urobiť dve veci:

  • Zaregistrujte ju pre injekciu závislosti;
  • Vytvorte triedu, ktorá povie AutoMapperu, ako spracovať mapovanie tried.

Najprv otvorte triedu Startup. V metóde ConfigureServices za posledný riadok pridajte nasledujúci kód:

services.AddAutoMapper ();

Tento riadok sa zaoberá všetkými potrebnými konfiguráciami aplikácie AutoMapper, ako je napríklad registrácia injekcie závislosti a skenovanie aplikácie počas spúšťania, aby sa nakonfigurovali mapovacie profily.

Teraz v koreňovom adresári pridajte nový priečinok s názvom Mapovanie a potom pridajte triedu s názvom ModelToResourceProfile. Zmena kódu týmto spôsobom:

Trieda zdedí profil, typ triedy, ktorý používa program AutoMapper na kontrolu fungovania našich mapovaní. Na konštruktore vytvoríme mapu medzi triedou modelu kategórie a triedou kategórie zdrojov. Pretože vlastnosti tried majú rovnaké názvy a typy, nemusíme pre ne používať žiadnu špeciálnu konfiguráciu.

Posledný krok spočíva v zmene radiča kategórií na použitie mapovania objektov pomocou aplikácie AutoMapper.

Zmenil som konštruktora, aby získal inštanciu implementácie IMapperu. Tieto metódy rozhrania môžete použiť na použitie metód mapovania AutoMapper.

Zmenil som tiež metódu GetAllAsync na mapovanie nášho výčtu kategórií na výpočet zdrojov pomocou metódy Mapa. Táto metóda prijíma inštanciu triedy alebo kolekcie, ktorú chceme zmapovať, a prostredníctvom všeobecných definícií typov definuje, na aký typ triedy alebo kolekcie sa musí mapovať.

Všimnite si, že sme ľahko zmenili implementáciu bez toho, aby sme museli prispôsobovať triedu služieb alebo úložisko, jednoducho injektovaním novej závislosti (IMapper) konštruktorovi.

Vkladanie závislosti umožňuje údržbu vašej aplikácie a jej ľahkú zmenu, pretože na pridanie alebo odstránenie funkcií nemusíte prerušiť implementáciu kódu.

Pravdepodobne ste si uvedomili, že nielen trieda radičov, ale všetky triedy, ktoré prijímajú závislosti (vrátane samotných závislostí), boli automaticky rozlíšené, aby dostali správne triedy podľa väzbových konfigurácií.

Injekcia závislosti je úžasná, však?

Teraz znova spustite API pomocou príkazu na spustenie dotnetu a prejdite na http: // localhost: 5000 / api / categories, aby ste videli novú odpoveď JSON.

Toto sú údaje z odpovedí, ktoré by ste mali vidieť

Náš koncový bod GET už máme. Teraz vytvorme nový koncový bod pre kategórie POST (create).

Krok 9 - Vytvorenie nových kategórií

Keď sa zaoberáme tvorbou zdrojov, musíme sa starať o veľa vecí, ako napríklad:

  • Overovanie a integrita údajov;
  • Oprávnenie vytvárať zdroje;
  • Chyba pri manipulácii;
  • Protokolovanie.

V tomto tutoriále nebudem demonštrovať, ako sa vysporiadať s autentifikáciou a autorizáciou, ale môžete vidieť, ako ľahko implementovať tieto funkcie čítaním môjho tutoriálu pri autentifikácii webovým tokenom JSON.

Existuje tiež veľmi populárny rámec s názvom ASP.NET Identity, ktorý poskytuje vstavané riešenia týkajúce sa bezpečnosti a registrácie používateľov, ktoré môžete použiť vo svojich aplikáciách. Zahŕňa poskytovateľov, ktorí pracujú s EF Core, napríklad vstavaný IdentityDbContext, ktorý môžete použiť. Viac sa o tom môžete dozvedieť tu.

Napíšeme koncový bod protokolu HTTP POST, ktorý bude pokrývať ostatné scenáre (okrem protokolovania, ktoré sa môžu meniť podľa rôznych rozsahov a nástrojov).

Pred vytvorením nového koncového bodu potrebujeme nový zdroj. Tento prostriedok bude mapovať údaje, ktoré klientske aplikácie odosielajú do tohto koncového bodu (v tomto prípade názov kategórie), do triedy našej aplikácie.

Keďže vytvárame novú kategóriu, zatiaľ nemáme ID, čo znamená, že potrebujeme zdroj, ktorý predstavuje kategóriu obsahujúcu iba jej názov.

Do priečinka Zdroje pridajte novú triedu s názvom SaveCategoryResource:

Všimnite si atribúty Povinné a MaxLength použité pre vlastnosť Názov. Tieto atribúty sa nazývajú anotácie údajov. Potrubie ASP.NET Core používa tieto metaúdaje na overenie požiadaviek a odpovedí. Ako názov napovedá, názov kategórie je povinný a má maximálnu dĺžku 30 znakov.

Teraz definujme tvar nového koncového bodu API. Pridajte nasledujúci kód do radiča kategórií:

Rámci hovoríme, že toto je koncový bod HTTP POST pomocou atribútu HttpPost.

Všimnite si typ odpovede tejto metódy, Úloha . Metódy prítomné v triedach kontrolérov sa nazývajú akcie a majú tento podpis, pretože po aplikácii akcie môžeme vrátiť viac ako jeden možný výsledok.

V takom prípade, ak je názov kategórie neplatný alebo ak sa niečo pokazí, musíme vrátiť 400-chybovú odpoveď (zlá požiadavka), ktorá vo všeobecnosti obsahuje chybové hlásenie, ktoré môžu klientské aplikácie použiť na vyriešenie problému, alebo môžeme mať 200 odpoveď (úspech) s údajmi, ak je všetko v poriadku.

Existuje mnoho typov akcií, ktoré môžete použiť ako odpoveď, ale vo všeobecnosti môžeme toto rozhranie použiť a ASP.NET Core na to použije predvolenú triedu.

Atribút FromBody hovorí ASP.NET Core, aby analyzoval údaje tela žiadosti do našej novej triedy prostriedkov. To znamená, že keď sa do našej aplikácie odošle JSON obsahujúci názov kategórie, rámec ju automaticky analyzuje do našej novej triedy.

Teraz implementujme našu logiku trasy. Aby sme mohli úspešne vytvoriť novú kategóriu, musíme postupovať podľa niekoľkých krokov:

  • Najprv musíme potvrdiť prichádzajúcu žiadosť. Ak je žiadosť neplatná, musíme vrátiť chybnú odpoveď na požiadavku obsahujúcu chybové správy;
  • Potom, ak je požiadavka platná, musíme zmapovať náš nový prostriedok do triedy modelov našej kategórie pomocou programu AutoMapper;
  • Teraz musíme zavolať našej službe a povedať jej, aby uložila novú kategóriu. Ak sa logika ukladania vykoná bez problémov, mala by vrátiť odpoveď obsahujúcu údaje o našej novej kategórii. Ak nie, malo by nám to naznačiť, že proces zlyhal, a možné chybové hlásenie;
  • Nakoniec, ak dôjde k chybe, vrátime zlú požiadavku. Ak nie, mapujeme náš nový model kategórie na zdroj kategórie a vraciame úspešnú odpoveď klientovi, ktorý obsahuje nové údaje kategórie.

Zdá sa, že je to komplikované, ale túto logiku je skutočne ľahké implementovať pomocou architektúry služieb, ktorú sme štruktúrovali pre naše API.

Začnime overením prichádzajúcej žiadosti.

Krok 10 - Overenie platnosti žiadosti pomocou modelového stavu

Radiče ASP.NET Core majú vlastnosť nazývanú ModelState. Táto vlastnosť je vyplnená počas vykonávania žiadosti pred dosiahnutím nášho vykonania akcie. Je to inštancia ModelStateDictionary, triedy, ktorá obsahuje informácie o tom, či je žiadosť platná, a chybové chybové hlásenia o validácii.

Kód koncového bodu zmeňte takto:

Kód skontroluje, či je stav modelu (v tomto prípade údaje odoslané v tele žiadosti) neplatný, a skontroluje naše anotácie údajov. Ak to tak nie je, API vráti zlú požiadavku (so stavovým kódom 400) a predvolené chybové správy, ktoré nám poskytli metaúdaje anotácií.

Metóda ModelState.GetErrorMessages () ešte nie je implementovaná. Ide o metódu rozšírenia (metóda, ktorá rozširuje funkčnosť už existujúcej triedy alebo rozhrania), ktorú budem implementovať na prevod chýb validácie na jednoduché reťazce, aby som sa vrátil klientovi.

Pridajte nový priečinok Rozšírenia v koreňovom adresári nášho rozhrania API a potom pridajte novú triedu ModelStateExtensions.

Všetky metódy rozšírenia by mali byť statické, ako aj triedy, v ktorých sú deklarované. To znamená, že nespracovávajú konkrétne údaje inštancie a že sa načítajú iba raz pri spustení aplikácie.

Toto kľúčové slovo pred vyhlásením parametra hovorí kompilátoru C #, aby ho považoval za metódu rozšírenia. Výsledkom je, že ju môžeme nazvať ako normálnu metódu tejto triedy, pretože tam, kde chceme rozšírenie použiť, zahrnujeme príslušnú direktívu using.

Rozšírenie využíva dotazy LINQ, veľmi užitočnú funkciu .NET, ktorá nám umožňuje vyhľadávať a transformovať údaje pomocou reťaziteľných výrazov. Výrazy tu transformujú metódy overovania chýb do zoznamu reťazcov obsahujúcich chybové správy.

Skôr ako prejdete na ďalší krok, importujte obor názvov Supermarket.API.Rozšírenia do radiča kategórií.

pomocou Supermarket.API.Extensions;

Pokračujme vo vykonávaní našej logiky koncového bodu mapovaním nášho nového zdroja do triedy modelovej kategórie.

Krok 11 - Mapovanie nového zdroja

Už sme definovali mapovací profil na transformáciu modelov na zdroje. Teraz potrebujeme nový profil, ktorý dokáže inverzne.

Pridajte novú triedu ResourceToModelProfile do zložky Mapping:

Nie je tu nič nové. Vďaka kúzlu injekcie závislosti AutoMapper automaticky zaregistruje tento profil pri spustení aplikácie a nemusíme meniť iné miesto, aby sme ho mohli používať.

Teraz môžeme zmapovať náš nový zdroj do príslušnej triedy modelov:

Krok 12 - Použitie vzoru požiadavka-odpoveď na zvládnutie ukladacej logiky

Teraz musíme implementovať najzaujímavejšiu logiku: uložiť novú kategóriu. Očakávame, že to naše služby urobia.

Logika ukladania môže zlyhať z dôvodu problémov pri pripojení k databáze alebo pravdepodobne preto, že akékoľvek interné obchodné pravidlo zneplatňuje naše údaje.

Ak sa niečo pokazí, nemôžeme jednoducho vyhodiť chybu, pretože by to mohlo zastaviť API a klientska aplikácia by nevedela, ako problém vyriešiť. Tiež by sme mohli mať nejaký protokolovací mechanizmus, ktorý by zaznamenával chybu.

Zmluva o spôsobe ukladania, to znamená, podpis metódy a typ odpovede, nás musí naznačovať, či bol proces vykonaný správne. Ak bude proces v poriadku, dostaneme údaje o kategórii. Ak nie, musíme dostať aspoň chybové hlásenie, v ktorom sa uvádza, prečo tento proces zlyhal.

Túto funkciu môžeme implementovať použitím vzoru požiadavka-odpoveď. Tento vzorec podnikového dizajnu zhŕňa naše požiadavky a parametre odozvy do tried ako spôsob zapuzdrenia informácií, ktoré naše služby použijú na spracovanie niektorých úloh a na vrátenie informácií triede, ktorá službu používa.

Tento model nám poskytuje niekoľko výhod, napríklad:

  • Ak potrebujeme zmeniť našu službu, aby sme dostali viac parametrov, nemusíme porušovať jej podpis;
  • Môžeme definovať štandardnú zmluvu pre našu žiadosť a / alebo odpovede;
  • Dokážeme zvládnuť obchodnú logiku a potenciálne zlyhania bez toho, aby sme zastavili proces podávania žiadostí, a nebudeme musieť používať veľa skúšobných blokov.

Vytvoríme štandardný typ odozvy pre naše služby, ktoré riešia zmeny údajov. Pre každú požiadavku tohto typu chceme vedieť, či je žiadosť vykonaná bez problémov. Ak zlyhá, chceme klientovi vrátiť chybovú správu.

V priečinku Doména v rámci Služieb pridajte nový adresár s názvom Komunikácia. Pridajte do nej novú triedu s názvom BaseResponse.

Toto je abstraktná trieda, ktorú zdedia naše typy odpovedí.

Abstrakcia definuje vlastnosť Úspech, ktorá povie, či boli žiadosti úspešne dokončené, a vlastnosť Správa, ktorá bude mať chybové hlásenie, ak niečo zlyhá.

Všimnite si, že tieto vlastnosti sú vyžadované a iba zdedené triedy môžu tieto údaje nastavovať, pretože podriadené triedy musia tieto informácie odovzdávať prostredníctvom funkcie konštruktora.

Tip: Nie je dobré definovať základné triedy pre všetko, pretože základné triedy spájajú váš kód a bránia vám v jeho ľahkej úprave. Radšej používajte kompozíciu pred dedičstvom.
Pokiaľ ide o rozsah tohto rozhrania API, nie je skutočne problém používať základné triedy, pretože naše služby sa príliš nerozrastú. Ak si uvedomíte, že služba alebo aplikácia bude rásť a meniť sa často, nepoužívajte základnú triedu.

Teraz do toho istého priečinka pridajte novú triedu s názvom SaveCategoryResponse.

Typ odpovede tiež nastavuje vlastnosť kategórie, ktorá v prípade úspešného splnenia požiadavky bude obsahovať údaje o našej kategórii.

Všimnite si, že som pre túto triedu definoval troch rôznych konštruktorov:

  • Súkromná, ktorá odovzdá parametre úspechu a správy základnej triede a tiež nastaví vlastnosť Kategória;
  • Konštruktor, ktorý ako parameter dostane iba kategóriu. Táto vytvorí úspešnú odpoveď a vyzve súkromného konštruktora, aby nastavil príslušné vlastnosti;
  • Tretí konštruktor, ktorý špecifikuje iba správu. Tento sa použije na vytvorenie reakcie na zlyhanie.

Pretože C # podporuje viacero konštruktorov, zjednodušili sme vytváranie reakcií bez toho, aby sme definovali odlišnú metódu na zvládnutie tejto situácie, a to iba pomocou rôznych konštruktorov.

Teraz môžeme zmeniť naše servisné rozhranie a pridať novú zmluvu o spôsobe ukladania.

Zmeňte rozhranie ICategoryService takto:

K tejto metóde jednoducho odovzdáme kategóriu a zvládne všetku logiku potrebnú na uloženie modelových údajov, organizovanie úložísk a ďalšie potrebné služby, ktoré to umožňujú.

Všimnite si, že tu nevytváram konkrétnu triedu požiadaviek, pretože na vykonanie tejto úlohy nepotrebujeme žiadne ďalšie parametre. V počítačovom programovaní existuje koncept s názvom KISS - skratka pre Keep It Simple, Stupid. V zásade sa v nej hovorí, že by ste si mali nechať svoju aplikáciu čo najjednoduchšiu.

Pri navrhovaní aplikácií si to nezabudnite: aplikujte iba to, čo potrebujete na vyriešenie problému. Neprekonštruujte svoju aplikáciu.

Teraz môžeme dokončiť logiku koncového bodu:

Po overení údajov žiadosti a mapovaní prostriedku na náš model odovzdáme túto službu našej službe, aby údaje pretrvávala.

Ak niečo zlyhá, API vráti zlú požiadavku. Ak nie, API mapuje novú kategóriu (teraz vrátane údajov, ako je napríklad nové ID) do nášho predtým vytvoreného zdroja kategórie a pošle ho klientovi.

Teraz implementujme skutočnú logiku služby.

Krok 13 - Databázová logika a vzorec jednotky práce

Pretože budeme v databáze pretrvávať údaje, v našom úložisku potrebujeme novú metódu.

Pridajte novú metódu AddAsync do rozhrania ICategoryRepository:

Teraz implementujme túto metódu v našej skutočnej triede archívov:

Tu do našej sady jednoducho pridávame novú kategóriu.

Keď pridáme triedu do DBSet <>, EF Core začne sledovať všetky zmeny, ktoré sa vyskytnú v našom modeli, a tieto údaje použije v aktuálnom stave na generovanie dopytov, ktoré budú vkladať, aktualizovať alebo mazať modely.

Súčasná implementácia jednoducho pridá model do našej sady, ale naše údaje sa stále neuložia.

V kontextovej triede existuje metóda nazývaná SaveChanges, ktorú musíme zavolať, aby sa dotazy skutočne vykonali do databázy. Nevolal som to tu, pretože úložisko by nemalo trvať na údajoch, je to iba zbierka objektov v pamäti.

Táto téma je veľmi kontroverzná aj medzi skúsenými vývojármi .NET, ale dovoľte mi vysvetliť vám, prečo by ste nemali volať triedy SaveChanges v triedach úložísk.

Pojem úložisko môžeme chápať koncepčne ako akúkoľvek inú zbierku prítomnú v rámci .NET framework. Pri práci so zbierkou v .NET (a mnohých ďalších programovacích jazykoch, ako sú Javascript a Java), môžete vo všeobecnosti:

  • Pridajte k nemu nové položky (napríklad keď tlačíte údaje do zoznamov, polí a slovníkov);
  • Nájsť alebo filtrovať položky;
  • Odstránenie položky zo zbierky;
  • Vymeňte danú položku alebo ju aktualizujte.

Pomyslite na zoznam zo skutočného sveta. Predstavte si, že píšete nákupný zoznam na nákup vecí v supermarkete (aká je náhoda, nie?).

V zozname napíšete všetko ovocie, ktoré potrebujete kúpiť. Do tohto zoznamu môžete pridať ovocie, ovocie odstrániť, ak sa vzdáte nákupu alebo môžete nahradiť názov ovocia. Do zoznamu však nemôžete uložiť ovocie. Nemá zmysel hovoriť takúto vec obyčajnou angličtinou.

Tip: Pri navrhovaní tried a rozhraní v objektovo orientovaných programovacích jazykoch sa pokúste použiť prirodzený jazyk na kontrolu, či sa zdá, že robíte správne.
Napríklad má zmysel hovoriť, že človek implementuje rozhranie človeka, ale nemá zmysel hovoriť, že človek implementuje účet.

Ak chcete „uložiť“ zoznamy ovocia (v tomto prípade kúpiť všetko ovocie), platíte to a supermarket spracúva údaje o zásobách, aby skontroloval, či musia kúpiť viac ovocia od poskytovateľa alebo nie.

Rovnaká logika môže byť použitá pri programovaní. Úložiská by nemali ukladať, aktualizovať ani mazať údaje. Namiesto toho by ju mali delegovať na inú triedu, aby zvládli túto logiku.

Pri ukladaní údajov priamo do úložiska je ďalší problém: transakcie nemôžete používať.

Predstavte si, že naša aplikácia má mechanizmus protokolovania, ktorý ukladá určité používateľské meno a akciu vykonanú pri každej zmene údajov rozhrania API.

Teraz si predstavte, že z nejakého dôvodu voláte do služby, ktorá aktualizuje používateľské meno (nejde o bežný scenár, ale zvážme to).

Súhlasíte s tým, že ak chcete zmeniť meno používateľa v tabuľke fiktívnych používateľov, musíte najprv aktualizovať všetky protokoly, aby ste správne vedeli, kto túto operáciu vykonal, však?

Teraz si predstavte, že sme implementovali metódu aktualizácie pre používateľov a protokoly v rôznych úložiskách a obidve volajú SaveChanges. Čo sa stane, ak jedna z týchto metód zlyhá v priebehu procesu aktualizácie? Skončíte s nekonzistentnosťou údajov.

Zmeny by sme mali uložiť do databázy až po dokončení všetkého. Aby sme to dosiahli, musíme použiť transakciu, ktorá je v podstate vlastnosťou, ktorú väčšina databáz implementuje na ukladanie údajov až po dokončení komplexnej operácie.

„- Dobre, takže ak tu veci nemôžeme uložiť, kam by sme to mali urobiť?“

Bežným vzorcom na riešenie tohto problému je vzorec Jednotka práce. Tento vzor pozostáva z triedy, ktorá prijíma našu inštanciu AppDbContext ako závislosť a vystavuje metódy na začatie, dokončenie alebo zrušenie transakcií.

Na riešenie tohto problému použijeme jednoduchú implementáciu jednotky práce.

Pridajte nové rozhranie do priečinka Repositories v doménovej vrstve s názvom IUnitOfWork:

Ako vidíte, odhaľuje iba metódu, ktorá asynchrónne dokončí operácie správy údajov.

Teraz pridáme skutočnú implementáciu.

Pridajte novú triedu s názvom UnitOfWork do priečinka RepositoriesRepositories vrstvy Perzistencia:

Je to jednoduchá, čistá implementácia, ktorá uloží všetky zmeny do databázy až po dokončení úpravy pomocou úložísk.

Ak skúmate implementácie vzoru Jednotka práce, nájdete zložitejšie implementácie operácií rollback.

Pretože EF Core už implementuje vzor úložiska a jednotku práce v zákulisí, nemusíme sa starať o metódu vrátenia.

" - Čo? Prečo teda musíme vytvárať všetky tieto rozhrania a triedy? “

Oddelenie logiky perzistencie od obchodných pravidiel poskytuje mnoho výhod, pokiaľ ide o opätovné použitie a údržbu kódu. Ak použijeme EF Core priamo, skončíme s zložitejšími triedami, ktoré nebude ľahké zmeniť.

Predstavte si, že v budúcnosti sa rozhodnete zmeniť rámec ORM na iný, napríklad Dapper, alebo ak z dôvodu výkonu musíte implementovať jednoduché dotazy SQL. Ak prepojíte logiku svojich dopytov so svojimi službami, bude ťažké zmeniť logiku, pretože to musíte urobiť v mnohých triedach.

Pomocou vzoru úložiska môžete jednoducho implementovať novú triedu úložiska a spojiť ju pomocou injekcie závislosti.

Takže v zásade, ak EF Core využívate priamo vo svojich službách a vy musíte niečo zmeniť, dostanete to:

Ako som už povedal, EF Core implementuje vzory pracovných a úložných priestorov v zákulisí. Naše vlastnosti DbSet <> môžeme považovať za úložiská. SaveChanges tiež zachováva údaje iba v prípade úspechu pre všetky operácie databázy.

Teraz, keď viete, čo je jednotka práce a prečo ju používať v úložiskách, implementujme logiku skutočnej služby.

Vďaka našej oddelenej architektúre môžeme jednoducho prejsť inštanciu UnitOfWork ako závislosť pre túto triedu.

Naša obchodná logika je dosť jednoduchá.

Najprv sa pokúsime pridať novú kategóriu do databázy a potom sa rozhranie API pokúsi uložiť a zabaliť všetko do bloku try-catch.

Ak niečo zlyhá, API zavolá nejakú službu fiktívneho protokolovania a vráti odpoveď označujúcu zlyhanie.

Ak proces skončí bez problémov, aplikácia vráti úspešnú odpoveď a pošle údaje o našej kategórii. Jednoduché, však?

Tip: V aplikáciách v skutočnom svete by ste nemali zabaliť všetko do všeobecného bloku vyskúšania, ale všetky možné chyby by ste mali riešiť osobitne.
Jednoduché pridanie bloku vyskúšania nepokryje väčšinu možných neúspešných scenárov. Nezabudnite opraviť spracovanie chýb náradia.

Posledným krokom pred testovaním nášho rozhrania API je prepojenie rozhrania jednotky práce s príslušnou triedou.

Pridajte tento nový riadok do metódy ConfigureServices triedy Startup:

services.AddScoped  ();

Teraz to vyskúšajme!

Krok 14 - Testovanie koncového bodu POST pomocou programu Postman

Spustite našu aplikáciu znova pomocou dotnet run.

Prehliadač nemôžeme použiť na testovanie koncového bodu POST. Použime spoločnosť Postman na otestovanie našich koncových bodov. Je to veľmi užitočný nástroj na testovanie RESTful API.

Otvorte aplikáciu Postman a zatvorte úvodné správy. Zobrazí sa obrazovka, ako je táto:

Obrazovka ukazujúca možnosti testovania koncových bodov

Zmeňte predvolený GET do políčka výberu na POST.

Zadajte adresu API do poľa Zadajte žiadosť URL.

Musíme poskytnúť údaje tela žiadosti, ktoré sa majú odoslať do nášho rozhrania API. Kliknite na položku ponuky Body a potom zmeňte možnosť zobrazenú pod ňou na surovú.

Pošťák zobrazí možnosť Text vpravo. Zmeňte ho na JSON (application / json) a prilepte nasledujúce údaje JSON nižšie:

{
  "názov": ""
}
Obrazovka tesne pred odoslaním žiadosti

Ako vidíte, pošleme do nášho nového koncového bodu prázdny reťazec mien.

Kliknite na tlačidlo Odoslať. Dostanete výstup ako je tento:

Ako vidíte, naša logika overovania funguje!

Pamätáte si overovaciu logiku, ktorú sme vytvorili pre koncový bod? Tento výstup je dôkazom, že funguje!

Všimnite si tiež 400 stavový kód zobrazený vpravo. Výsledok BadRequest automaticky pridá tento stavový kód k odpovedi.

Teraz zmeňme údaje JSON na platné, aby sme videli novú odpoveď:

Nakoniec sme očakávali výsledok

Rozhranie API správne vytvorilo náš nový prostriedok.

Až doteraz môže naše rozhranie API vytvárať a vytvárať kategórie. Dozvedeli ste sa veľa vecí o jazyku C #, kostre ASP.NET Core a tiež o bežných prístupoch k navrhovaniu štruktúr API.

Pokračujme v rozhraní API našich kategórií a vytvoríme koncový bod na aktualizáciu kategórií.

Odvtedy, čo som vám vysvetlil väčšinu pojmov, urýchlime vysvetlenia a sústredím sa na nové témy, aby som nestratil čas. Poďme!

Krok 15 - Aktualizácia kategórií

Na aktualizáciu kategórií potrebujeme koncový bod HTTP PUT.

Logika, ktorú musíme kódovať, je veľmi podobná POST:

  • Najprv musíme potvrdiť prichádzajúcu požiadavku pomocou ModelState;
  • Ak je požiadavka platná, API by malo namapovať prichádzajúci prostriedok na modelovú triedu pomocou AutoMapper;
  • Potom musíme zavolať našej službe a oznámiť jej, aby aktualizovala kategóriu, pričom uvedie ID príslušnej kategórie a aktualizované údaje;
  • Ak v databáze neexistuje kategória s daným ID, vrátime zlú požiadavku. Namiesto toho by sme mohli použiť výsledok programu NotFound, ale na tomto rozsahu to skutočne nezáleží, pretože klientskym aplikáciám poskytujeme chybové hlásenie;
  • Ak je logika ukladania správne vykonaná, služba musí vrátiť odpoveď obsahujúcu aktualizované údaje kategórie. Ak nie, malo by nám to naznačiť, že proces zlyhal, a správu s uvedením dôvodu;
  • Nakoniec, ak dôjde k chybe, API vráti zlú požiadavku. Ak nie, mapuje aktualizovaný model kategórie na zdroj kategórie a vracia úspešnú odpoveď klientskej aplikácii.

Pridajme novú metódu PutAsync do triedy kontrolérov:

Ak ju porovnáte s logikou POST, všimnete si, že tu máme iba jeden rozdiel: Atribút HttPut určuje parameter, ktorý by daná cesta mala dostať.

Tento koncový bod nazveme ID kategórie ako posledný fragment adresy URL, napríklad / api / categories / 1. Potrubie ASP.NET Core analyzuje tento fragment na parameter s rovnakým názvom.

Teraz musíme definovať podpis metódy UpdateAsync do rozhrania ICategoryService:

Teraz prejdime k skutočnej logike.

Krok 16 - Aktualizačná logika

Ak chcete aktualizovať našu kategóriu, najprv musíme vrátiť aktuálne údaje z databázy, ak existujú. Musíme ho tiež aktualizovať do nášho DBSet <>.

Pridajte do nášho rozhrania ICategoryService dve nové zmluvy o metódach:

Definovali sme metódu FindByIdAsync, ktorá asynchrónne vráti kategóriu z databázy a metódu aktualizácie. Venujte pozornosť tomu, že metóda aktualizácie nie je asynchrónna, pretože rozhranie API EF Core nevyžaduje asynchrónnu metódu na aktualizáciu modelov.

Teraz implementujme skutočnú logiku do triedy CategoryRepository:

Nakoniec môžeme kódovať logiku služieb:

Rozhranie API sa pokúša získať kategóriu z databázy. Ak je výsledok null, vrátime odpoveď s oznámením, že kategória neexistuje. Ak kategória existuje, musíme si nastaviť nový názov.

Rozhranie API sa potom pokúša uložiť zmeny, napríklad keď vytvárame novú kategóriu. Po dokončení procesu služba vráti úspešnú odpoveď. Ak nie, logika logovania sa vykoná a koncový bod dostane odpoveď obsahujúcu chybovú správu.

Teraz to vyskúšajme. Najprv pridajme novú kategóriu, aby sme mohli použiť platný identifikátor. Mohli by sme použiť identifikátory kategórií, ktoré vkladáme do našej databázy, ale chcem to urobiť týmto spôsobom, aby som vám ukázal, že naše API bude aktualizovať správny zdroj.

Spustite aplikáciu znova a pomocou Postmanu POST novú kategóriu do databázy:

Pridaním novej kategórie ju môžete aktualizovať neskôr

Ak máte v ruke platné ID, zmeňte možnosť POST na PUT do políčka výberu a pridajte hodnotu ID na koniec adresy URL. Zmeňte vlastnosť name na iné meno a odošlite požiadavku na kontrolu výsledku:

Údaje kategórie boli úspešne aktualizované

Do koncového bodu API môžete odoslať žiadosť GET, aby ste sa uistili, že ste správne upravili názov kategórie:

To je teraz výsledkom žiadosti GET

Poslednou operáciou, ktorú musíme vykonať pre kategórie, je vylúčenie kategórií. Urobíme to tak, že vytvoríme koncový bod odstránenia protokolu HTTP.

Krok 17 - Odstránenie kategórií

Logiku odstránenia kategórií je možné jednoducho implementovať, pretože väčšina metód, ktoré potrebujeme, bola vytvorená už skôr.

Toto sú nevyhnutné kroky, aby naša cesta fungovala:

  • Rozhranie API musí zavolať našej službe a povedať, aby odstránila našu kategóriu a uviedla príslušné ID;
  • Ak v databáze neexistuje kategória s daným ID, služba by mala vrátiť správu, ktorá ju označí;
  • Ak sa logika odstránenia vykoná bez problémov, služba by mala vrátiť odpoveď obsahujúcu údaje o odstránenej kategórii. Ak nie, malo by nám to naznačiť, že proces zlyhal, a možné chybové hlásenie;
  • Nakoniec, ak dôjde k chybe, API vráti zlú požiadavku. Ak nie, API mapuje aktualizovanú kategóriu na prostriedok a vracia úspešnú odpoveď klientovi.

Začnime pridaním novej logiky koncového bodu:

Atribút HttpDelete tiež definuje šablónu id.

Pred pridaním podpisu DeleteAsync do nášho rozhrania ICategoryService musíme urobiť malý refaktoring.

Nová metóda služby musí vrátiť odpoveď obsahujúcu údaje kategórie, rovnako ako v prípade metód PostAsync a UpdateAsync. Na tento účel by sme mohli znovu použiť funkciu SaveCategoryResponse, ale v tomto prípade údaje neukladáme.

Aby sme sa vyhli vytvoreniu novej triedy s rovnakým tvarom, aby sme splnili túto požiadavku, môžeme jednoducho premenovať našu SaveCategoryResponse na CategoryResponse.

Ak používate kód Visual Studio, môžete otvoriť triedu SaveCategoryResponse, umiestniť kurzor myši nad názov triedy a premenovať triedu pomocou možnosti Zmeniť všetky výskyty:

Jednoduchý spôsob, ako zmeniť názov vo všetkých súboroch

Nezabudnite tiež premenovať názov súboru.

Pridáme podpis metódy DeleteAsync do rozhrania ICategoryService:

Pred implementáciou logiky odstránenia potrebujeme novú metódu v našom úložisku.

Pridajte podpis metódy Remove do rozhrania ICategoryRepository:

void Remove (kategória kategória);

A teraz pridajte skutočnú implementáciu do triedy úložiska:

EF Core vyžaduje, aby inštancia nášho modelu bola odovzdaná do metódy Odstrániť, aby sa správne pochopilo, ktorý model odstránime, namiesto jednoduchého odovzdania ID.

Nakoniec implementujme logiku do triedy CategoryService:

Nie je tu nič nové. Služba sa pokúsi nájsť kategóriu podľa ID a potom zavolá náš archív na odstránenie kategórie. Nakoniec jednotka práce dokončí transakciu vykonávajúcu skutočnú operáciu do databázy.

„- Hej, ale čo výrobky každej kategórie? Nemusíte najprv vytvárať úložisko a odstraňovať produkty, aby ste sa vyhli chybám? “

Odpoveď znie nie. Vďaka mechanizmu sledovania EF Core, rámec načíta model z databázy, rámec vie, aké vzťahy má model. Ak ju odstránime, EF Core vie, že by mala najskôr odstrániť všetky súvisiace modely rekurzívne.

Túto funkciu môžeme zakázať pri mapovaní našich tried do databázových tabuliek, ale tento tutoriál je mimo rozsah. Ak sa chcete dozvedieť viac o tejto funkcii, pozrite sa sem.

Teraz je čas vyskúšať náš nový koncový bod. Spustite aplikáciu znova a pošlite požiadavku DELETE pomocou Postmana nasledovne:

Ako vidíte, rozhranie API odstránilo existujúcu kategóriu bez problémov

Poslaním žiadosti GET môžeme skontrolovať, či naše rozhranie API správne funguje:

V dôsledku toho teraz dostávame iba jednu kategóriu

Dokončili sme API kategórií. Teraz je čas prejsť na API produktov.

Krok 18 - Products API

Doteraz ste sa naučili, ako implementovať všetky základné slovesá HTTP na spracovanie operácií CRUD s ASP.NET Core. Poďme na ďalšiu úroveň implementácie našich produktov API.

Nebudem znova podrobne popisovať všetky slovesá HTTP, pretože by to bolo vyčerpávajúce. V záverečnej časti tohto tutoriálu sa budem venovať iba žiadosti GET, aby som vám ukázal, ako zahrnúť súvisiace entity do dopytovania údajov z databázy a ako používať atribúty Popis, ktoré sme definovali pre hodnoty výčtu EUnitOfMeasurement.

Pridajte nový radič do priečinka Controllers s názvom ProductsController.

Predtým, ako tu niečo napíšete, musíme vytvoriť produktový prostriedok.

Dovoľte mi obnoviť vašu pamäť a znova ukázať, ako by mal náš zdroj vyzerať:

{
 [
  {
   "id": 1,
   "name": "Sugar",
   "množstvobalenie": 1,
   „unitOfMeasurement“: „KG“
   "category": {
   "id": 3,
   "name": "Sugar"
   }
  },
  … // Iné produkty
 ]
}

Chceme pole JSON obsahujúce všetky produkty z databázy.

Údaje JSON sa od modelu produktu líšia dvoma vecami:

  • Merná jednotka sa zobrazuje kratším spôsobom a zobrazuje iba jej skratku;
  • Vytvárame údaje kategórie bez zahrnutia vlastnosti CategoryId.

Na vyjadrenie mernej jednotky môžeme namiesto typu enumu použiť vlastnosť jednoduchého reťazca (mimochodom, pre dáta JSON nemáme predvolený typ enumu, takže ho musíme transformovať na iný typ).

Teraz, keď teraz upravíme nový zdroj, vytvorme ho. Pridajte novú triedu ProductResource do priečinka Zdroje:

Teraz musíme nakonfigurovať mapovanie medzi triedou modelu a našou novou triedou zdrojov.

Konfigurácia mapovania bude takmer rovnaká ako konfigurácia použitá pre iné mapovania, ale tu musíme zvládnuť transformáciu nášho enumu EUnitOfMeasurement na reťazec.

Pamätáte si atribút StringValue aplikovaný na typy výčtu? Teraz vám ukážem, ako extrahovať tieto informácie pomocou výkonnej funkcie rámca .NET: API Reflection.

Reflection API je výkonná sada zdrojov, ktorá nám umožňuje extrahovať a manipulovať s metadátami. Mnoho rámcov a knižníc (vrátane samotného ASP.NET Core) využíva tieto zdroje na zvládnutie mnohých vecí v zákulisí.

Teraz sa pozrime, ako to funguje v praxi. Pridajte novú triedu do priečinka Extensions s názvom EnumExtensions.

Pri prvom prezeraní kódu sa to môže zdať strašidelné, ale nie je to také zložité. Poďme rozobrať definíciu kódu, aby sme pochopili, ako to funguje.

Najprv sme definovali druhovú metódu (metódu, ktorá môže prijať viac ako jeden typ argumentu, v tomto prípade reprezentovaný vyhlásením TEnum), ktorý prijíma daný výčtu ako argument.

Keďže enum je rezervované kľúčové slovo v C #, pred názov parametra sme pridali znak @, aby sa stalo platným názvom.

Prvým krokom vykonávania tejto metódy je získanie informácií o type (definícia triedy, rozhrania, výčtu alebo štruktúry) parametra pomocou metódy GetType.

Potom metóda získa špecifickú hodnotu výčtu (napríklad Kilogram) pomocou GetField (@ enum.ToString ()).

Nasledujúci riadok nájde všetky atribúty popisu použité na hodnotu enumerácie a uloží ich údaje do poľa (v niektorých prípadoch môžeme špecifikovať viacero atribútov pre tú istú vlastnosť).

Posledný riadok používa kratšiu syntax na kontrolu, či máme pre typ výčtu aspoň jeden atribút popisu. Ak áno, vrátime hodnotu Popis poskytovanú týmto atribútom. Ak nie, vrátime výpočet ako reťazec pomocou predvoleného odovzdávania.

? operátor (operátor s nulovými podmienkami) pred prístupom k svojmu majetku skontroluje, či je hodnota null.

?? operátor (operátor nulového zhustenia) oznámi aplikácii, aby vrátila hodnotu vľavo, ak nie je prázdna, alebo hodnotu vpravo inak.

Teraz, keď máme metódu rozšírenia na extrahovanie popisov, nakonfigurujme naše mapovanie medzi modelom a zdrojom. Vďaka programu AutoMapper to dokážeme iba s jedným ďalším riadkom.

Otvorte triedu ModelToResourceProfile a zmeňte kód týmto spôsobom:

Táto syntax hovorí programu AutoMapper, aby pomocou novej metódy rozšírenia previedol našu hodnotu EUnitOfMeasurement na reťazec obsahujúci jeho popis. Jednoduché, však? Môžete si prečítať oficiálnu dokumentáciu, aby ste pochopili úplnú syntax.

Všimnite si, že sme nedefinovali žiadnu konfiguráciu mapovania pre vlastnosť kategórie. Pretože sme predtým nakonfigurovali mapovanie pre kategórie a pretože produktový model má vlastnosť kategórie rovnakého typu a názvu, AutoMapper implicitne vie, že by mal mapovať pomocou príslušnej konfigurácie.

Teraz pridáme kód koncového bodu. Zmeňte kód produktu Controller:

V podstate rovnaká štruktúra definovaná pre radič kategórií.

Poďme na servisnú časť. Pridajte nové rozhranie IProductService do zložky Services na vrstve domény:

Mali by ste si uvedomiť, že pred skutočnou implementáciou novej služby potrebujeme úložisko.

Do príslušného priečinka pridajte nové rozhranie s názvom IProductRepository:

Teraz implementujme úložisko. Musíme ich implementovať takmer rovnako, ako sme to urobili pre archív kategórií, s výnimkou toho, že pri vyhľadávaní údajov musíme vrátiť príslušné údaje o kategóriách každého produktu.

EF Core v predvolenom nastavení nezahŕňa súvisiace entity do vašich modelov pri dopytovaní údajov, pretože to môže byť veľmi pomalé (predstavte si model s desiatimi príbuznými subjektami, všetky všetky súvisiace entity majú svoje vlastné vzťahy).

Na zahrnutie údajov o kategóriách potrebujeme iba jeden riadok navyše:

Všimnite si výzvu na zahrnutie (p => p.Category). Túto syntax môžeme spojiť, aby sme pri dotazovaní údajov zahrnuli čo najviac entít. EF Core ho pri prevedení výberu preloží na spojenie.

Teraz môžeme implementovať triedu ProductService rovnakým spôsobom, ako sme to urobili pre kategórie:

Zaviažme nové závislosti a zmeníme triedu Startup:

Nakoniec, pred testovaním API, zmeňme triedu AppDbContext tak, aby zahrnovala niektoré produkty pri inicializácii aplikácie, aby sme videli výsledky:

Pri inicializácii aplikácie som pridal dva fiktívne produkty, ktoré ich spájajú do kategórií, ktoré nasadzujeme.

Čas vyskúšať! Spustite API znova a pošlite požiadavku GET na / api / products pomocou Postmana:

Voila! Tu sú naše produkty

A to je všetko! Blahoželáme!

Teraz máte základňu o tom, ako zostaviť RESTful API pomocou technológie ASP.NET Core pomocou oddelenej architektúry. Naučili ste sa veľa vecí v rámci .NET Core framework, ako pracovať s C #, základy EF Core a AutoMapper a mnoho užitočných vzorov, ktoré sa majú použiť pri navrhovaní vašich aplikácií.

Môžete skontrolovať úplnú implementáciu API obsahujúceho ostatné slovesá HTTP pre produkty a skontrolovať úložisko Github:

záver

ASP.NET Core je skvelý rámec, ktorý sa používa pri vytváraní webových aplikácií. Dodáva sa s mnohými užitočnými API, ktoré môžete použiť na vytváranie čistých a udržiavateľných aplikácií. Považujte to za možnosť pri vytváraní profesionálnych aplikácií.

Tento článok sa nezaoberal všetkými aspektmi profesionálneho rozhrania API, ale naučili ste sa všetky základy. Naučili ste sa tiež veľa užitočných vzorcov na riešenie vzorcov, ktorým čelíme každý deň.

Dúfam, že sa vám tento článok páčil, a dúfam, že to bolo pre vás užitočné. Ďakujeme za vaše pripomienky, aby sme pochopili, ako to môžem vylepšiť.

Odkazy na ďalšie vzdelávanie

.NET Core Tutorials - Microsoft Docs

ASP.NET Core Documentation - Dokumenty Microsoft