5. poglavje: Ustvarjanje in objava spletnega API-ja v storitvi Azure
Mateja in Svetlana sta ugotovili, da bi morali podatki za aplikacijo za tehnike izvirati iz obstoječih sistemov prek spletnega API-ja, zato sodelujeta, da bi ugotovili, točno katere informacije so potrebne in v kateri obliki zapisa. Svetlana bo nato ustvarila spletno aplikacijo, ki izpostavlja ustrezen spletni API in ga uredi za gostovanje v storitvi Azure. Aplikacija se lahko poveže s storitvijo Azure iz kjer koli, kjer je brezžična povezava.
Opredelitev operacij s spletnim API-jem: upravljanje terenske zaloge
Zaslon Prebrskaj razdelka aplikacije upravljanje terenske zaloge prikazuje seznam delov za grelnike in sisteme za klimatizacijo (imenovane enostavno deli grelnika). Zaslon Podrobnosti omogoča tehniku, da si ogleda več informacij o izbranem delu.
V obstoječi zbirki podatkov zaloge (imenovani InventoryDB), so informacije od delih v eni tabeli, imenovani BoilerParts. Svetlana ugotovi, da bi moral spletni API podpirati naslednje zahteve:
- Priklic vseh delov grelnika.
- Priklic podrobnosti o delu, glede na ID dela.
Opredelitev operacij s spletnim API-jem: terenska zbirka znanja
V obstoječem sistemu zbirka podatkov zbirke znanja (imenovana KnowledgeDB) vsebuje tri tabele, ki beležijo in upravljajo odnose med nasveti, serviserji in deli:
- Nasveti, ki vsebuje podrobnosti nasveta. Vsak nasvet obsega povzetek v eni vrstici, ki opredeljuje določeno težavo (zadeva), in podrobnejšo razlago z opisom, kako odpraviti težavo (telo). Vsak nasvet se tudi sklicuje na del in serviserja, ki je zabeležil nasvet.
- BoilerParts, ki vsebuje seznam delov, na katere se sklicujejo nasveti. Podrobnosti o samih delih so shranjene v tabeli BoilerParts v zbirki podatkov InventoryDB.
- Serviserji, ki navaja tehnike, ki so ustvarili vsak nasvet.
Del aplikacije v zvezi z zbirko znanja trenutno vsebuje samo označbo mesta za zaslon Brskalnik. Mateja želi uveljaviti naslednjo funkcionalnost:
Tehnik določi iskalni izraz na zaslonu Prebrskaj, da poišče vse ujemajoče nasvete. Ujemanje je lahko v imenu dela, na katerega se nasvet nanaša, besedilu v zadevi ali telesu nasveta ali imenu tehnika, ki je strokovnjak glede posebnega kosa opreme.
Ko so najdeni vsi ujemajoči nasveti, lahko tehnik izbere nasvet, da si ogleda njegove podrobnosti.
Tehnik lahko tudi doda nove nasvete v zbirko znanja ter doda opombe in komentarje v obstoječe nasvete.
Zbirka znanja je velika in raste, poizvedovanje po več tabelah in stolpcih pa lahko vključuje kompleksno logiko, za katero je potrebna znatna računalniška moč. Za zmanjšanje obremenitve spletnega API-ja se Kiana odloči za uporabo Azure Cognitive Search za zagotavljanje funkcije iskanja, kot je opisano prej. Za podporo aplikacije se Svetlana odloči, da so od spletnega API-ja zahtevane naslednje operacije:
Iskanje podrobnosti določenega nasveta zbirke znanja iz tabele Nasveti.
Posodobitev obstoječega nasveta zbirke znanja v tabeli Nasveti.
Dodajanje novega nasveta zbirke znanja v tabelo Nasveti, kar lahko vključuje tudi dodajanje vrstic tabeli BoilerParts in Serviserji, če določen del ali serviser trenutno nimata zabeleženih nobenih nasvetov. Rutina, ki dejansko izvaja logiko za dodajanjem novega nasveta bo izvedena kot logična aplikacija, priklicana iz storitve Power Apps.
Opredelitev operacij s spletnim API-jem: terensko razporejanje
Ob razporejanju terminov tehnikov je poleg poizvedovanja po, dodajanja in odstranjevanja terminov potrebno tudi beleženje informacij o strankah. V obstoječem sistemu terminov so ti podatki zabeleženi v treh tabelah v zbirki podatkov SchedulesDB:
- Termini, ki vsebuje podrobnosti o vsakem terminu, vključno z datumom, časom, težavo in tehnikom, ki je dodeljen opravilu.
- Stranke, ki vsebuje podrobnosti vsake stranke, vključno njeno ime, naslov in podrobnosti za stik.
- Serviserji, ki navaja vsakega tehnika, ki izvaja termine.
Opomba
Zbirka podatkov dejansko vsebuje četrto tabelo, imenovano AppointmentsStatus. Ta tabela vsebuje seznam veljavnih vrednosti za stanje termina in je enostavno iskanje, ki ga uporabijo drugi deli obstoječega sistema terminov.
Svetlana se odloči, da bi bile naslednje operacije koristne za del aplikacije v zvezi s terenskim razporejanjem:
- Iskanje vseh terminov za določenega tehnika.
- Iskanje vseh terminov za trenutni dan za določenega tehnika.
- Iskanje naslednjega načrtovanega termina za določenega tehnika.
- Posodobitev podrobnosti termina, kot je dodajanje opomb ali fotografije.
- Iskanje podrobnosti o stranki.
Izdelava spletnega API-ja: upravljanje terenske zaloge
Obstoječi sistemi shranjujejo podatke z uporabo zbirke podatkov SQL Azure. Svetlana se odloči izdelati spletni API z uporabo tehnologije Entity Framework Core, ker lahko ta pristop ustvari veliko kode, ki samodejno poizveduje po, vstavlja in posodablja podatke. Predloga spletnega API-ja, ki jo zagotavlja Microsoft, lahko ustvari tudi opise Swagger, ki opisujejo vsako operacijo v API-ju. Ti opisi so uporabni za preskušanje operacij API-ja. Številna orodja lahko te informacije uporabljajo za integracijo API-ja z drugimi storitvami, kot je upravljanje vmesnikov API Azure.
Svetlana je začela s funkcionalnostjo terenske zaloge, ker je to najbolj preprost del. Operacije terenske zaloge v spletnem API-ju poizvedujejo po eni tabeli, BoilerParts, v zbirki podatkov InventoryDB. Ta tabela vsebuje stolpce, prikazane na naslednji sliki.

Svetlana je pri izdelavi spletnega API-ja uporabila pristop »najprej koda«. S to strategijo je naredila naslednje:
Določila je lasten razred modela C#, ki je zrcalil strukturo tabele BoilerParts v zbirki podatkov InventoryDB.
Ustvarila je razred konteksta Entity Framework, ki ga spletni API uporablja za povezovanje z zbirko podatkov, da izvaja poizvedbe.
Konfigurirala je razred konteksta za povezovanje z zbirko podatkov InventoryDB v storitvi Azure.
Uporabila je orodja ukazne vrstice Entity Framework za ustvarjanje razreda kontrolnika spletnega API-ja, ki izvaja zahteve HTTP REST za vsako od operacij, ki jo je mogoče izvesti v tabeli BoilerParts.
Uporabila API Swagger za preskušanje spletnega API-ja.
Naslednja slika prikazuje strukturo spletnega API-ja na visoki ravni.

Svetlana je uporabila postopek za ustvarjanje spletnega API-ja z uporabo orodij ukazne vrstice .NET 5.0 in storitve Visual Studio Code:
Odprite terminalsko okno v programu Visual Studio Code.

Zaženite naslednji ukaz, da ustvarite nov projekt spletnega API-ja z imenom FieldEngineerApi.
dotnet new webapi -o FieldEngineerApiOdprite mapo FieldEngineerApi.

Odstranite vzorčni kontrolnik WeatherForecastController.cs in datoteko razreda WeatherForecast.cs, ki jo je ustvarila predloga spletnega API-ja.

V oknu Terminal v projekt dodajte naslednje pakete in orodja Entity Framework skupaj s podporo za uporabo strežnika SQL Server.
dotnet add package Microsoft.EntityFrameworkCore.SqlServer dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design dotnet add package Microsoft.EntityFrameworkCore.Design dotnet add package Microsoft.AspNetCore.Mvc.NewtonsoftJson dotnet tool install --global dotnet-ef dotnet tool install --global dotnet-aspnet-codegeneratorV mapi FieldEngineerApi ustvarite novo ime mape z imenom Modeli.

V mapi Modeli ustvarite datoteko kode C# z imenom BoilerPart.cs.

V to datoteko dodajte naslednje lastnosti in polja. Te lastnosti in polja zrcalijo strukturo tabele BoilerParts v zbirki podatkov InventoryDB.
using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace FieldEngineerApi.Models { public class BoilerPart { [Key] public long Id { get; set; } public string Name { get; set; } public string CategoryId { get; set; } [Column(TypeName = "money")] public decimal Price { get; set; } public string Overview { get; set; } public int NumberInStock { get; set; } public string ImageUrl { get; set; } } }V mapi Modeli ustvarite še eno datoteko kode C# z imenom InventoryContext.cs. Dodajte naslednjo kodo v ta razred. Razred zagotavlja povezavo med kontrolnikom (ki bo ustvarjen naslednji) in zbirko podatkov.
using Microsoft.EntityFrameworkCore; namespace FieldEngineerApi.Models { public class InventoryContext : DbContext { public InventoryContext(DbContextOptions<InventoryContext> options) : base(options) { } public DbSet\<BoilerPart\> BoilerParts { get; set; } } }Uredite datoteko appsettings.Development.json za projekt in dodajte razdelek ConnectionStrings z naslednjim nizom povezave InventoryDB. Zamenjajte <server name> z imenom strežnika SQL Database, ki ste ga ustvarili, da hrani zbirko podatkov InventoryDB.
{ "ConnectionStrings": { "InventoryDB": "Server=tcp*:<server name>*.database.windows.net,1433;Initial Catalog=InventoryDB;Persist Security Info=False;User ID=sqladmin;Password=Pa55w.rd;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } } }Pomembno
Samo za namene tega vodnika niz povezave vsebuje ID uporabnika in geslo za zbirko podatkov. V produkcijskem sistemu teh elementov nikoli ne shranjujte v jasnem besedilu v konfiguracijski datoteki.
Uredite datoteko Startup.cs in dodajte naslednje z uporabo direktiv na seznam na začetku datoteke.
using FieldEngineerApi.Models; using Microsoft.EntityFrameworkCore;V razredu Zagon poiščite metodo ConfigureServices. Dodajte naslednjo izjavo v to metodo.
public void ConfigureServices(IServiceCollection services) { services.AddDbContext<InventoryContext>(options => options.UseSqlServer(Configuration.GetConnectionString("InventoryDB"))); services.AddControllers(); ... }Spremenite metodo Konfiguriranje in omogočite uporabniški vmesnik za Swagger, tudi ko se aplikacija izvaja v produkcijskem načinu, kot je prikazano (ta sprememba vključuje preselitev dveh priklicev metode app.UseSwagger iz izjave if).
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "FieldEngineerApi v1")); ... }Pomembno
Ta sprememba omogoča, da je končna točka Swagger izpostavljena za integracijo upravljanja vmesnikov API. Ko je bilo upravljanje vmesnikov API konfigurirano, bi morali premakniti to kodo nazaj v izjavo if in znova uvesti spletni API. Nikoli ne pustite končne točke Swagger odprte v produkcijskem sistemu.
V oknu Terminal zaženite naslednji ukaz za ustvarjanje kontrolnika BoilerParts iz razreda modela BoilerPart in razreda konteksta InventoryContext
dotnet aspnet-codegenerator controller ^ -name BoilerPartsController -async -api ^ -m BoilerPart -dc InventoryContext -outDir ControllersKontrolnik BoilerParts je treba ustvariti v mapi Kontrolniki.
[!NOTE] Znak za prekinitev vrstice ^ prepozna samo Windows. Če uporabljate Visual Studio Code na sistemu Linux, namesto njega uporabite znak \.
Odprite datoteko BoilerParts.cs v mapi Kontrolniki in si oglejte njeno vsebino. Razred BoilerPartsController izpostavlja naslednje metode REST:
- GetBoilerParts(), ki vrne seznam vseh predmetov BoilerPart iz zbirke podatkov.
- GetBoilerPart(long id), ki pridobi podrobnosti navedenega dela grelnika.
- PutBoilerPart(long id, BoilerPart boilerPart), ki posodobi del grelnika v zbirki podatkov s podrobnostmi v predmetu BoilerPart, določenimi kot parameter.
- PostBoilerPart(BoilerPart boilerPart), ki ustvari nov del grelnika.
- DeleteBoilerPart(long id), ki odstrani podrobnosti navedenega dela grelnika.
Opomba
Za aplikacijo za tehnike sta potrebni samo dve metodi Pridobi, druge pa so koristne za namizno aplikacijo za upravljanje zaloge (ni zajeta v tem vodniku).
Sestavite in izdelajte spletni API.
dotnet build
Spletni API mora biti izdelan brez sporočenih napak ali opozoril.
Uvajanje spletnega API-ja v Azure: upravljanje terenske zaloge
Svetlana je uvedla in preskusila spletni API z izvedbo opravil po naslednjih navodilih:
Z uporabo razširitve računa Azure v programu Visual Studio Code se vpišite v naročnino za Azure.
Iz terminalskega okna v programu Visual Studio Code ustvarite novo skupino virov z imenom webapi_rg v naročnini Azure. V naslednjem ukazu nadomestite <location> z vam najbližjo regijo Azure.
az group create ^ --name webapi_rg ^ --location <location>Ustvarite načrt storitve aplikacije Azure za zagotavljanje virov za gostovanje spletnega API-ja.
az appservice plan create ^ --name webapi_plan ^ --resource-group webapi_rg ^ --sku F1Opomba
F1 je brezplačen SKU za načrte storitve aplikacije. Zagotavlja omejen pretok in zmogljivost ter je primeren samo za razvojne namene.
Ustvarite spletno aplikacijo Azure z uporabo načrta storitve aplikacije. Nadomestite <webapp name> z enoličnim imenom za spletno aplikacijo.
az webapp create ^ --name <webapp name> ^ --resource-group webapi_rg ^ --plan webapi_planV programu Visual Studio Code uredite datoteko appSettings.json in dodajte isti niz povezave, ki ste ga predhodno zapisali v datoteko appSettings.Development.json. Ne pozabite zamenjati <server name> z imenom strežnika SQL Database, ki ste ga ustvarili, da hrani zbirko podatkov InventoryDB.
{ "ConnectionStrings": { "InventoryDB": "Server=tcp:<server name>.database.windows.net,1433;Initial Catalog=InventoryDB;Persist Security Info=False;User ID=sqladmin;Password=Pa55w.rd;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"** }, "Logging": { "LogLevel": { "Default\: "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*" }V terminalskem oknu zapakirajte spletni API, pripravljen za uvedbo v Azure.
dotnet publish -c Release -o ./publishTa ukaz shrani zapakirane datoteke v mapo z imenom publish.
V programu Visual Studio Code z desno tipko miške kliknite mapo Objavi in nato izberite Uvedi v spletno aplikacijo.

Izberite ime spletne aplikacije, ki ste jo ustvarili prej v 4. koraku (<webapp name>). V naslednjem primeru je spletna aplikacija poimenovana my-fieldengineer-webapp.

Ob pozivu v pogovornem oknu programa Visual Studio Code izberite Uvedi za sprejem opozorila in uvedbo spletne aplikacije.

Preverite, ali je spletna aplikacija uspešno uvedena in se nato premaknite na spletno mesto.

Spletno mesto se bo odprlo v novem oknu brskalnika, vendar bo prikazalo napako HTTP 404 (ni mogoče najti). To pa zato, ker so operacije spletnega API-ja na voljo prek končne točke API in ne prek korena spletnega mesta. Spremenite URL na https://<webapp name>.azurewebsites.net/api/BoilerParts. Ta URI prikliče metodo GetBoilerParts v kontrolniku BoilerParts. Spletni API se mora odzvati z dokumentom JSON, v katerem so navedeni vsi deli grelnika v zbirki podatkov InventoryDB.

Spremenite URL v brskalniku na https://<webapp name>.azurewebsites.net/swagger. Prikaže se API Swagger. To je grafični uporabniški vmesnik, ki razvijalcu omogoča, da preveri in preskusi vsako od operacij v spletnem API-ju. Deluje tudi kot uporabno dokumentacijsko orodje.

Izberite GET poleg končne točke /api/BoilerParts/{id} in nato izberite Preskusi.

V polje ID vnesite ID dela in nato izberite Izvedi. To dejanje prikliče metodo GetBoilerPart(long id) v kontrolniku BoilerParts. Vrnilo bo dokument JSON s podrobnostmi dela ali napako HTTP 404, če ni najdenega ujemajočega se dela v zbirki podatkov.

Zaprite spletni brskalnik in se vrnite v Visual Studio Code.
Izdelava in uvajanje spletnega API-ja: terenska zbirka znanja
Operacije terenske zbirke znanja v spletnem API-ju delujejo v treh tabelah zbirke podatkov KnowledgeDB: Nasveti, BoilerParts in Serviserji. Naslednja slika prikazuje odnose med temi tabelami in stolpci, ki jih vsebujejo.

Svetlana je ubrala podoben pristop za zbirko podatkov terenske zbirke znanja, kot ga je uporabila za zbirko podatkov upravljanja terenske zaloge. Izvedla je opravila po naslednjih navodilih:
Ustvarite razrede modela C#, ki zrcalijo strukturo tabele Nasveti, BoilerParts in Serviserji v zbirki podatkov KnowledgeDB. Koda za vsakega od teh razredov je prikazana v nadaljevanju.
Opomba
Tabela BoilerParts v zbirki podatkov KnowledgeDB se razlikuje od tabele BoilerParts v zbirki podatkov InventoryDB. V izogib konflikta zaradi imena imajo razredi modelov za tabele v zbirki znanja KnowledgeDB predpono KnowledgeBase.
// KnowledgeBaseTips.cs using System.ComponentModel.DataAnnotations; namespace FieldEngineerApi.Models { public class KnowledgeBaseTip { [Key] public long Id { get; set; } public long KnowledgeBaseBoilerPartId { get; set; } public virtual KnowledgeBaseBoilerPart KnowledgeBaseBoilerPart { get; set; } public string KnowledgeBaseEngineerId { get; set; } public virtual KnowledgeBaseEngineer KnowledgeBaseEngineer { get; set; } public string Subject { get; set; } public string Body { get; set; } } }Opomba
ID serviserja je niz, ne številka. Razlog za to je, da obstoječi sistemi uporabljajo GUID-je za prepoznavanje tehnikov in drugih uporabnikov.
// KnowledgeBaseBoilerPart.cs using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace FieldEngineerApi.Models { public class KnowledgeBaseBoilerPart { [Key] public long Id { get; set; } public string Name { get; set; } public string Overview { get; set; } public virtual ICollection<KnowledgeBaseTip> KnowledgeBaseTips { get; set; } } }// KnowledgeBaseEngineer.cs using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace FieldEngineerApi.Models { public class KnowledgeBaseEngineer { [Key] public string Id { get; set; } [Required] public string Name { get; set; } public string ContactNumber { get; set; } public virtual ICollection<KnowledgeBaseTip> KnowledgeBaseTips { get; set; } } }Ustvarite še en razred konteksta Entity Framework, ki ga spletni API uporablja za povezovanje z zbirko podatkov KnowledgeDB.
// KnowledgeBaseContext.cs using Microsoft.EntityFrameworkCore; namespace FieldEngineerApi.Models { public class KnowledgeBaseContext : DbContext { public KnowledgeBaseContext(DbContextOptions<KnowledgeBaseContext> options) : base(options) { } public DbSet<KnowledgeBaseBoilerPart> BoilerParts { get; set; } public DbSet<KnowledgeBaseEngineer> Engineers { get; set; } public DbSet<KnowledgeBaseTip> Tips { get; set; } } }Uredite datoteko appsettings.Development.json za projekt in dodajte naslednji niz povezave KnowledgDB v razdelek ConnectionStrings. Zamenjajte <server name> z imenom strežnika SQL Database, ki ste ga ustvarili, da hrani zbirko podatkov KnowledgeDB.
{ "ConnectionStrings": { "InventoryDB": "Server=tcp:...", "KnowledgeDB": "Server=tcp:<server name>.database.windows.net,1433;Initial Catalog=KnowledgeDB;Persist Security Info=False;User ID=sqladmin;Password=Pa55w.rd;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" }, "Logging": { ... } } }Pomembno
Samo za namene tega vodnika niz povezave vsebuje ID uporabnika in geslo za zbirko podatkov. V produkcijskem sistemu teh elementov nikoli ne shranjujte v jasnem besedilu v konfiguracijski datoteki.
Uredite datoteko Startup.cs in v metodi ConfigureServices dodajte naslednje izjave.
public void ConfigureServices(IServiceCollection services) { services.AddDbContext<InventoryContext>...; services.AddDbContext<KnowledgeBaseContext>(options => options.UseSqlServer(Configuration.GetConnectionString("KnowledgeD"))); services.AddControllers().AddNewtonsoftJson( options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore** ); services.AddControllers(); ... }Druga izjava nadzoruje način, kako so podatki serializirani, ko se pridobijo. Nekateri razredi modelov imajo sklice na druge razrede modelov, ki se nato sklicujejo na nadaljnje razrede modelov. Nekateri od teh sklicev lahko privedejo do rekurzivnih zank (entiteta A se sklicuje na entiteto B, ki se sklicuje nazaj na entiteto A, ki se spet sklicuje na entiteto B, in tako dalje). Možnost ReferenceLoopHandling povzroči, da serializator prezre takšne zanke v podatkih ter vrne samo entiteto in predmete, na katere se neposredno sklicuje, to pa je vse.
V oknu Terminal zaženite naslednji ukaz za ustvarjanje kontrolnikov iz razredov modelov KnowledgeBaseBoilerTip, KnowledgeBaseBoilerPart in KnowledgeBaseEngineer ter razreda konteksta KnowledgeBaseContext.
dotnet aspnet-codegenerator controller ^ -name KnowledgeBaseTipController -async -api ^ -m KnowledgeBaseTip ^ -dc KnowledgeBaseContext -outDir Controllers dotnet aspnet-codegenerator controller ^ -name KnowledgeBaseBoilerPartController -async -api ^ -m KnowledgeBaseBoilerPart ^ -dc KnowledgeBaseContext -outDir Controllers dotnet aspnet-codegenerator controller ^ -name KnowledgeBaseEngineerController -async -api ^ -m KnowledgeBaseEngineer ^ -dc KnowledgeBaseContext -outDir ControllersVse tri kontrolnike je treba ustvariti v mapi Kontrolniki.
Uredite datoteko KnowledgeBaseBoilerPartController.cs. Ta datoteka vsebuje kodo za kontrolnik KnowledgeBaseBoilerPart. Slediti bi morala istemu vzorcu kot prej ustvarjen razred BoilerPartsController, z izpostavljanjem metod REST, ki omogočajo odjemalcu, da navaja, poizveduje po, vstavlja, posodablja in briše entitete. Dodajte naslednjo metodo GetTipsForPart v kontrolnik.
[Route("api/[controller]")] [ApiController] public class KnowledgeBaseBoilerPartController : ControllerBase { private readonly KnowledgeBaseContext _context; public KnowledgeBaseBoilerPartController(KnowledgeBaseContext context) { _context = context; } // GET: api/KnowledgeBaseBoilerPart/5/Tips [HttpGet("{id}/Tips")] public async Task<ActionResult<IEnumerable<KnowledgeBaseTip>>>GetTipsForPart(long id) { return await _context.Tips.Where( t => t.KnowledgeBaseBoilerPartId == id).ToListAsync(); } ... }Ta metoda vrne vse nasvete zbirke znanja, ki se sklicujejo na določen del. Da najde te informacije, poizveduje po tabeli Nasveti v zbirki podatkov prek predmeta KnowledgeBaseContext.
Uredite datoteko KnowledgeBaseEngineerController.cs in dodajte naslednjo metodo v razred KnowledgeBaseEngineerController.
[Route("api/[controller]")] [ApiController] public class KnowledgeBaseEngineerController : ControllerBase { private readonly KnowledgeBaseContext _context; public KnowledgeBaseEngineerController(KnowledgeBaseContext context) { _context = context; } // GET: api/KnowledgeBaseEngineer/5/Tips [HttpGet("{id}/Tips")] public async Task\<ActionResult<IEnumerable<KnowledgeBaseTip>>> GetTipsForEngineer(string id) { return await _context.Tips.Where(t => t.KnowledgeBaseEngineerId == id).ToListAsync(); } ... }Metoda GetTipsForEngineer najde vse nasvete zbirke znanja, ki jih objavi določen serviser.
V oknu Terminal sestavite in izdelajte spletni API.
dotnet buildSpletni API mora biti izdelan brez sporočenih napak ali opozoril.
Uredite datoteko appSettings.json in dodajte niz povezave za zbirko podatkov KnowledgeDB. Ta niz bi moral biti enak tistemu, ki ste ga prej zapisali v datoteko appSettings.Development.json.
{ "ConnectionStrings": { "InventoryDB": ..., "KnowledgeDB": "Server=tcp:<server name>.database.windows.net,1433;Initial Catalog=KnowledgeDB;Persist Security Info=False;User ID=sqladmin;Password=Pa55w.rd;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" }, "Logging": { ... }, "AllowedHosts": "*" }V oknu Terminal zapakirajte spletni API, pripravljen za uvedbo v Azure.
dotnet publish -c Release -o ./publishV programu Visual Studio Code z desno tipko miške kliknite mapo Objavi in nato izberite Uvedi v spletno aplikacijo. Uvedite v isto spletno aplikacijo Azure, kot ste jo ustvarili prej. Dovolite, da čarovnik prepiše obstoječo spletno aplikacijo z novo kodo.
Ko je uvedba končana, se premaknite na spletno mesto, toda spremenite URL v brskalniku na https://<webapp name>.azurewebsites.net/swagger. Operacije za kontrolnike KnowledgeBaseBoilerPart, KnowledgeBaseEngineer in KnowldgeBaseTip bi morale biti navedene poleg obstoječih operacij BoilerParts. Preverite, ali operacije KnowledgeBaseBoilerPart vključujejo operacijo GET za URI /api/KnowledgeBaseBoilerPart/{id}/Tips, operacije KnowledgeBaseEngineer pa vključujejo operacijo GET za URI /api/KnowledgeBaseEngineer/{id}/Tips.

Izdelava in uvajanje spletnega API-ja: terensko razporejanje
Operacije terenskega razporejanja uporabljajo tabele Termini, AppointmentStatuses (to je enostavna tabela za iskanje, ki navaja veljavne vrednosti stanj terminov), Stranke in Serviserji, prikazane na naslednji sliki. Te tabele so shranjene v zbirki podatkov SchedulesDB.

Za ustvarjanje operacij spletnega API-ja za del sistema terensko razporejanje je Svetlana izvedla naslednja opravila:
Ustvarite razrede modela C#, ki zrcalijo strukturo tabele AppointmentStatus, Termini, Stranke in Serviserji v zbirki podatkov SchedulesDB. Naslednja koda prikazuje vsakega od teh razredov.
Opomba
Razred modela za tabelo Serviserji je imenovan ScheduleEngineer, da se razlikuje od tabele Serviserji v zbirki podatkov InventoryDB.
// AppointmentStatus.cs using Newtonsoft.Json; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace FieldEngineerApi.Models { public class AppointmentStatus { [Key] public long Id { get; set; } public string StatusName { get; set; } [JsonIgnore] public virtual ICollection<Appointment> Appointments { get; set; } } }// Appointment.cs using System; using System.ComponentModel.DataAnnotations; namespace FieldEngineerApi.Models { public class Appointment { [Key] public long Id { get; set; } [Required] public long CustomerId { get; set; } public virtual Customer Customer { get; set; } public string ProblemDetails { get; set; } [Required] public long AppointmentStatusId { get; set; } public virtual AppointmentStatus AppointmentStatus { get; set; } public string EngineerId { get; set; } public virtual ScheduleEngineer Engineer { get ; set; } [Display(Name = "StartTime")] [DataType(DataType.DateTime)] [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy H:mm:ss}")] public DateTime StartDateTime { get; set; } public string Notes { get; set; } public string ImageUrl { get; set; } } }// Customer.cs using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace FieldEngineerApi.Models { public class Customer { [Key] public long Id { get; set; } [Required] public string Name { get; set; } public string Address { get; set; } public string ContactNumber { get; set; } public virtual ICollection<Appointment> Appointments { get; set; } } }// ScheduleEngineer.cs using Newtonsoft.Json; using System.ComponentModel.DataAnnotations; using System.Collections.Generic; namespace FieldEngineerApi.Models { public class ScheduleEngineer { [Key] public string Id { get; set; } [Required] public string Name { get; set; } public string ContactNumber { get; set; } [JsonIgnore] public virtual ICollection<Appointment> Appointments { get; set; } } }Ustvarite kontekst Entity Framework, ki ga spletni API uporablja za povezovanje z zbirko podatkov SchedulesDB.
// ScheduleContext.cs using System; using Microsoft.EntityFrameworkCore; namespace FieldEngineerApi.Models { public class ScheduleContext : DbContext { public ScheduleContext(DbContextOptions<ScheduleContext> options) : base(options) { } public DbSet<Appointment> Appointments { get; set; } public DbSet<AppointmentStatus> AppointmentStatuses { get; set; } public DbSet<Customer> Customers { get; set; } public DbSet<ScheduleEngineer> Engineers { get; set; } } }Uredite datoteko appsettings.Development.json za projekt in dodajte naslednji niz povezave SchedulesDB v razdelek ConnectionStrings. Zamenjajte <server name> z imenom strežnika SQL Database, ki ste ga ustvarili, da hrani zbirko podatkov KnowledgeDB.
{ "ConnectionStrings": { "InventoryDB": "Server=tcp*: ...", "KnowledgeDB": "Server=tcp; ... ", "SchedulesDB": "Server=tcp:<server name>.database.windows.net,1433;Initial Catalog=SchedulesDB;Persist Security Info=False;User ID=sqladmin;Password=Pa55w.rd;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" }, "Logging": { ... } } }Uredite datoteko Startup.cs in v metodi ConfigureServices dodajte naslednjo izjavo.
public void ConfigureServices(IServiceCollection services) { services.AddDbContext<InventoryContext>...; services.AddDbContex\<KnowledgeBaseContext>...; services.AddDbContext<ScheduleContext>(options => options.UseSqlServer(Configuration.GetConnectionString("SchedulesDB"))); services.AddControllers().AddNewtonsoftJson(...); ... }V oknu Terminal zaženite naslednji ukaz za ustvarjanje kontrolnikov iz razredov modelov Termin, Stranka in ScheduleEngineer ter razreda konteksta ScheduleContext.
Opomba
Ne ustvarite ločenega kontrolnika za model AppointmentStatus.
dotnet aspnet-codegenerator controller ^ -name AppointmentsController -async -api ^ -m Appointment ^ -dc ScheduleContext -outDir Controllers dotnet aspnet-codegenerator controller ^ -name CustomerController -async -api ^ -m Customer ^ -dc ScheduleContext -outDir Controllers dotnet aspnet-codegenerator controller ^ -name ScheduleEngineerController -async -api ^ -m ScheduleEngineer ^ -dc ScheduleContext -outDir ControllersUredite datoteko AppointmentsController.cs. V razredu AppointmentsController poiščite metodo GetAppointments. Prilagodite izjavo return, kot je prikazano. Ta sprememba zagotovi, da so informacije Stranka, Serviser in AppointmentStatus pridobljene kot del operacije GET; ta polja se sklicujejo na druge entitete, ki bi bile sicer puščene ničelne zaradi mehanizma počasnega nalaganja programa Entity Framework.
public class AppointmentsController : ControllerBase { private readonly ScheduleContext _context; public AppointmentsController(ScheduleContext context) { _context = context; } // GET: api/Appointments [HttpGet] public async Task<ActionResult<IEnumerable<Appointment>>> GetAppointments() { return await _context.Appointments .Include(c => c.Customer) .Include(e => e.Engineer) .Include(s => s.AppointmentStatus) .ToListAsync(); } ... }V isti datoteki prilagodite metodo GetAppointment(long id), kot je prikazano.
// GET: api/Appointments/5 [HttpGet("{id}")] public async Task<ActionResult<Appointment>> GetAppointment(long id) { var appointment = _context.Appointments .Where(a => a.Id == id) .Include(c => c.Customer) .Include(e => e.Engineer) .Include(s => s.AppointmentStatus); var appData = await appointment.FirstOrDefaultAsync(); if (appData == null) { return NotFound(); } return appData; }Ta različica metode ob pridobitvi izpolni polja Stranka, Serviser in AppointmentStatus za termin (pri počasnem nalaganju bi sicer ta polja ostala prazna).
Poiščite metodo PutAppointment in jo zamenjajte z naslednjo kodo. Ta različica metode PutAppointment vzame polja v terminu, ki jih lahko uporabnik prilagodi v aplikaciji, namesto popolnega predmeta Termin.
[HttpPut("{id}")] public async Task<IActionResult> PutAppointment(long id, string problemDetails, string statusName, string notes, string imageUrl) { var statusId = _context.AppointmentStatuses.First(s => s.StatusName == statusName).Id; var appointment = _context.Appointments.First(e => e.Id == id); if (appointment == null) { return BadRequest(); } appointment.ProblemDetails = problemDetails; appointment.AppointmentStatusId = statusId; appointment.Notes = notes; appointment.ImageUrl = imageUrl; _context.Entry(appointment).State = EntityState.Modified; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!AppointmentExists(id)) { return NotFound(); } else { throw; } } return NoContent(); }Opomba
Praviloma bi smele operacije PUT prilagoditi samo podatke, za katere ima uporabnik dovoljenje za posodobitev, ne nujno vsako polje v entiteti.
Odprite datoteko ScheduleEngineerController.cs in dodajte metodo GetScheduleEngineerAppointments v razred ScheduleEngineerController.
[Route("api/[controller]")] [ApiController] public class ScheduleEngineerController : ControllerBase { private readonly ScheduleContext _context; public ScheduleEngineerController(ScheduleContext context) { _context = context; } // GET: api/ScheduleEngineer/5/Appointments [HttpGet("{id}/Appointments")] public async Task<ActionResult<IEnumerable<Appointment>>> GetScheduleEngineerAppointments(string id) { return await _context.Appointments .Where(a => a.EngineerId == id) .OrderByDescending(a => a.StartDateTime) .Include(c => c.Customer) .Include(e => e.Engineer) .Include(s => s.AppointmentStatus) .ToListAsync(); } ... } These methods retrieve the appointments for the specified technician.Edit the CustomerController.cs file and add the GetAppointments and GetNotes methods, as shown, to the CustomerController class.
[Route("api/[controller]")] [ApiController] public class CustomerController : ControllerBase { private readonly ScheduleContext _context; public CustomerController(ScheduleContext context) { _context = context; } //GET: api/Customers/5/Appointments [HttpGet("{id}/Appointments")] public async Task<ActionResult<IEnumerable<Appointment>>> GetAppointments(long id) { return await _context.Appointments .Where(a => a.CustomerId == id) .OrderByDescending(a => a.StartDateTime) .ToListAsync(); } //GET: api/Customers/5/Notes [HttpGet("{id}/Notes")] public async Task<ActionResult<IEnumerable<object>>> GetNotes(long id) { return await _context.Appointments .Where(a => a.CustomerId == id) .OrderByDescending(a => a.StartDateTime) .Select(a => new {a.StartDateTime, a.ProblemDetails, a.Notes}) .ToListAsync(); } ... }Metoda GetAppointments poišče vse termine za določeno stranko. Metoda GetNotes pridobi vse opombe, ki jih je tehnik zabeležil ob prejšnjih obiskih stranke.
Uredite datoteko appSettings.json in dodajte niz povezave za zbirko podatkov KnowledgeDB. Ta niz bi moral biti enak tistemu, ki ste ga prej zapisali v datoteko appSettings.Development.json.
{ "ConnectionStrings": { "InventoryDB": ..., "KnowledgeDB": ..., "SchedulesDB": "Server=tcp:<server name>.database.windows.net,1433;Initial Catalog=SchedulesDB;Persist Security Info=False;User ID=sqladmin;Password=Pa55w.rd;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" }, "Logging": { ... }, "AllowedHosts": "*" }V oknu Terminal sestavite in izdelajte spletni API.
dotnet buildSpletni API mora biti izdelan brez sporočenih napak ali opozoril.
V oknu Terminal zapakirajte spletni API, pripravljen za uvedbo v Azure.
dotnet publish -c Release -o ./publishV programu Visual Studio Code z desno tipko miške kliknite mapo Objavi in nato izberite Uvedi v spletno aplikacijo. Uvedite v isto spletno aplikacijo Azure, kot ste jo ustvarili prej. Dovolite, da čarovnik prepiše obstoječo spletno aplikacijo z novo kodo.
Ko je uvedba končana, se premaknite na spletno mesto, toda spremenite URL v brskalniku na https://<webapp name>.azurewebsites.net/swagger. Preverite, ali so operacije za kontrolnike Termini, Stranka in ScheduleEngineer zdaj na voljo.
Spletni API je zdaj pripravljen za vključitev v aplikacijo.
Povratne informacije
Pošlji in prikaži povratne informacije za