Kapitel 5: Skapa och publicera ett webb-API i Azure
När vi har fastställt att data för teknikernas program ska komma från befintliga system via ett webb-API arbetar Maria och Kiana tillsammans för att avgöra exakt vilken information som behövs och i vilket format. Kiana skapar då en webbapp som visar rätt webb-API och ordnar att den finns i Azure. Appen kan ansluta till Azure var som helst där det finns en trådlös anslutning.
Definiera åtgärder för webb-API: Lagerhantering för fält
Skärmen Bläddra i avsnittet Lagerhantering på fält visar en lista över värmare och luftkonditioneringssystem (kallas bara värmardelar). Skärmen Detaljer gör att teknikern kan visa mer information om en vald del.
I den befintliga lagerdatabasen (med namnet InventoryDB) finns information om delar i en enkel tabell som kallas BoilerParts. Kiana bestämmer att webb-API:et ska stödja följande förfrågningar:
- Hämta alla värmardelar.
- Få information om en del, givet del-ID.
Definiera åtgärder för webb-API: fältkunskapsbasen
I det befintliga systemet innehåller kunskapsbasdatabasen (med namnet KnowledgeDB) tre tabeller som registrerar och hanterar relationer mellan tips, tekniker och delar:
- Tips, som innehåller information om ett tips. Varje tips ger en sammanfattning av en rad som identifierar ett visst problem (ämnet) och en mer detaljerad förklaring som beskriver hur du löser problemet (brödtexten). Varje tips refererar också till en del och teknikern som registrerade tipset.
- BoilerParts, som innehåller en lista över de delar som tipsen refererar till. Detaljerna för själva delarna lagras i tabellen BoilerParts i InventoryDB-databasen.
- Tekniker, som listar de tekniker som har skrivit varje tips.
Den kunskapsbasdel i programmet som för närvarande endast innehåller en platshållarskärm för Webbläsare. Maria vill implementera följande funktioner:
Teknikern anger en sökterm på skärmen Bläddra för att hitta alla matchande tips. Matchningen kan vara namnet på den del som tipset refererar till, text i ämnet eller brödtexten i tipset, eller namnet på en tekniker som är expert på ett visst utrustningsdelar.
När alla matchande tips har hittats kan teknikern välja ett tips för att visa informationen.
En tekniker kan också lägga till nya tips i kunskapsbasen och lägga till anteckningar och kommentarer i befintliga tips.
Kunskapsbasen är stor och växande, och att fråga över flera tabeller och kolumner kan innefatta komplex logik som kräver en stor beräkningskraft. För att minska belastningen på webb-API:et bestämmer sig Kiana för att använda Azure Cognitive Search för att tillhandahålla sökfunktionen enligt beskrivningen ovan. För att stöda programmet bestämmer sig Kiana för att följande åtgärder krävs från webb-API:et:
Hitta informationen i en viss kunskapsbas i tabellen Tips.
Uppdatera ett befintligt kunskapsbastips i tabellen Tips.
Lägg till ett nytt kunskapsbastips i tabellen Tips vilket även kan innebära att rader läggs till i tabellerna BoilerParts och Tekniker om den angivna delen eller teknikern för närvarande inte har några registrerade tips. Rutinen som egentligen utför logiken bakom att lägga till ett nytt tips implementeras som en logikapp som anropas från Power Apps.
Definiera åtgärder för webb-API: fältschemaläggning
För schemaläggning av avtalade tider för tekniker krävs det inte bara att fråga, lägga till och ta bort avtalade tider, utan även registrera information om kunder. I systemet för befintliga avtalade tider lagras dessa data i tre tabeller i SchedulesDB-databasen:
- Avtalade tider, som innehåller information om varje avtalad tid, t.ex. datum, tid, problem, anteckningar och tekniker som tilldelats uppgiften.
- Kunder, som innehåller information om varje kund, inklusive namn, adress och kontaktuppgifter.
- Tekniker som listar alla tekniker som deltar i avtalade tider.
Anteckning
Databasen innehåller en fjärde tabell med namnet AppointmentsStatus. Den här tabellen innehåller en lista över giltiga värden för en avtalad tids status och är bara ett uppslag som används av andra delar i det befintliga systemet för avtalade tider.
Kiana bestämmer sig för att följande åtgärder kan vara användbara för programmets fältschemaläggning:
- Hitta alla avtalade tider för en viss tekniker.
- Hitta alla avtalade tider för aktuell dag för en viss tekniker.
- Hitta nästa schemalagda avtalad tid för en viss tekniker.
- Uppdatera informationen om en avtalad tid, t.ex. lägga till anteckningar eller göra anteckningar.
- Hitta information om en kund.
Skapa webb-API: Lagerhantering för fält
De befintliga systemen lagrar data med hjälp av Azure SQL Database. Kiana bestämmer sig för att bygga webb-API:et med hjälp av Entity Framework Core, eftersom den här metoden kan generera mycket kod som frågor, infogar och uppdaterar data automatiskt. Microsofts web-API-mall kan också skapa swagger-beskrivningar som beskriver varje åtgärd i API:et. Beskrivningarna är användbara om du vill testa API-åtgärderna. Många verktyg kan använda den här informationen för att integrera API:et med andra tjänster, till exempel Azure API Management.
Kiana började med funktionen Fältinventering eftersom det här är det mest enkla. Åtgärder för fältinventering i Webb-API-frågan i en enskild tabell, BoilerParts i InventoryDB-databasen. Den här tabellen innehåller kolumnerna som visas i följande bild.
Kiana använde metoden "kod-först" för att bygga sitt webb-API, samt gjorde följande:
Definierade sin egen klass C#-modell som speglade strukturen i tabellen BoilerParts i databasen InventoryDB.
Skapade klassen kontext för Entity Framework som webb-API använder för att ansluta till databasen för att utföra frågor.
Konfigurerade kontextklassen att ansluta till InventoryDB-databasen i Azure.
Använde kommandoradsverktygen för Entity Framework för att skapa en klass för webb-API kontroller som implementerar HTTP REST-förfrågningar för de åtgärder som kan utföras mot tabellen BoilerParts.
Använde swagger API för att testa webb-API:et.
I följande bild visas webb-API:et med en hög struktur.
Kiana använde följande procedur för att skapa webb-API med .NET 6.0-kommandoradsverktyg och Visual Studio Code
Öppna ett terminalfönster i Visual Studio Code.
Kör följande kommando för att skapa ett nytt webb-API-projekt med namnet FieldEngineerApi.
dotnet new webapi -o FieldEngineerApi
Öppna mappen FieldEngineerApi.
Ta bort exemelkontrollanten WeatherForecastController.cs och klassfiler WeatherForecast.cs som skapades av mallen för webb-API.
I fönstret Terminal lägger du till följande Entity Framework-paket och -verktyg, tillsammans med stöd för att använda SQL Server, i projektet.
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-codegenerator
I mappen FieldEngineerApi skapa en ny mapp med namnet Modeller.
I mappen Modeller, skapa C# kodfil med namnet BoilerPart.cs.
Lägg till följande egenskaper och fält i den här filen. Dessa egenskaper och fält återspeglar strukturen i tabellen BoilerParts i databasen 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; } } }
I mappen Modeller, skapa C# kodfil med namnet InventoryContext.cs. Lägg till följande kod i klassen. Klassen tillhandahåller anslutningen mellan kontrollanten (som ska skapas härnäst) och databasen.
using Microsoft.EntityFrameworkCore; namespace FieldEngineerApi.Models { public class InventoryContext : DbContext { public InventoryContext(DbContextOptions<InventoryContext> options) : base(options) { } public DbSet\<BoilerPart\> BoilerParts { get; set; } } }
Redigera filen appsettings.Development.json för projektet och lägg till ett avsnitt ConnectionStrings med följande InventoryDB anslutningssträng. Ersätt <server name> med namnet på SQL Database-servern som du skapade för att lagra InventoryDB-databasen.
{ "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" } } }
Viktigt
I den här guiden finns endast anslutningssträngen användar-ID och lösenord för databasen. I ett produktionssystem bör du aldrig lagra objekten i klartext i en konfigurationsfil.
Redigera filen Startup.cs och lägg till följande i listan när du använder direktiv i listan i början av filen.
using FieldEngineerApi.Models; using Microsoft.EntityFrameworkCore;
I klassen Start, hitta metoden ConfigureServices. Lägg till följande instruktion i denna metod.
public void ConfigureServices(IServiceCollection services) { services.AddDbContext<InventoryContext>(options => options.UseSqlServer(Configuration.GetConnectionString("InventoryDB"))); services.AddControllers(); ... }
Ändra metoden Konfigurera och aktivera swagger-användargränssnittet även när programmet körs i produktionsläge, som visas (denna förändring innebär att de två metoderna för app.UseSwagger anropas utanför if-instruktion).
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")); ... }
Viktigt
Den här förändringen gör att swagger-slutpunkt synlig för API Management-integrering. När API Management har konfigurerats ska du flytta tillbaka den här koden i if-instruktionen och distribuera om webb-API:et. Lämna aldrig swagger-slutpunkt är öppen i ett produktionssystem.
I fönstret Terminal kör du följande kommando för att generera BoilerParts kontrollanten från BoilerPart modellklassen och InventoryContext kontextklassen.
dotnet aspnet-codegenerator controller ^ -name BoilerPartsController -async -api ^ -m BoilerPart -dc InventoryContext -outDir Controllers
Kontrollanten BoilerParts ska skapas i mappen Kontrollanter.
[!NOTE] Radbrytningstecknet ^ identifieras endast av Windows. Om du kör Visual Studio Code på ett Linux-system använder du tecknet \ i stället.
Öppna filen BoilerParts.cs i mappen kontrollanter och granska innehållet. Klassen BoilerPartsController visar följande REST-metoder:
- GetBoilerParts(), som returnerar en lista över alla objekt för BoilerPart från databasen.
- GetBoilerPart(long id), som hämtar information om den angivna värmardelen.
- PutBoilerPart(long id, BoilerPart boilerPart), som uppdaterar en värmardel i databasen med informationen i objektet BoilerPart som anges som en parameter.
- PostBoilerPart(BoilerPart boilerPart), som skapar en ny värmardel.
- DeleteBoilerPart(long id), som tar bort den angivna värmardelen från databasen.
Anteckning
Teknikerns program kräver endast de två Hämta-metoderna, men de andra är användbara för lagerhanteringsapparna på stationära datorer (finns inte med i den här guiden).
Kompilera och skapa webb-API:et.
dotnet build
Webb-API ska skapas utan att det rapporterar några fel eller varningar.
Distribuera webb-API till Azure: Lagerhantering för fält
Kiana distribuerat och testat webb-API:et genom att utföra följande uppgifter:
Använda Azure-kontotillägget i Visual Studio Code, logga in på din Azure-prenumeration.
Från terminalfönstret i Visual Studio Code, skapa en ny resursgrupp med namnet webapi_rg i din Azure-prenumeration. I följande kommando, ersätt <location> med närmaste Azure-region.
az group create ^ --name webapi_rg ^ --location <location>
Skapa en Azure App Service-plan för att tillhandahålla resurser för värdskapet för webb-API:et.
az appservice plan create ^ --name webapi_plan ^ --resource-group webapi_rg ^ --sku F1
Anteckning
F1 är den kostnadsfria SKU-tjänsten för App Service-planer. Det ger begränsat genomflöde och kapacitet och är endast lämpligt för utvecklingssyften.
Skapa en Azure-webbapp med hjälp av App Service-planen. Ersätt <webapp name> med ett unikt namn för webbprogrammet.
az webapp create ^ --name <webapp name> ^ --resource-group webapi_rg ^ --plan webapi_plan
I Visual Studio Code, redigera filen appSettings.json och lägg till samma anslutningssträng som du tidigare skrev till filen appSettings.Development.json. Kom ihåg att ersätta <server name> med namnet på SQL Database-servern som du skapade för att lagra InventoryDB-databasen.
{ "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": "*" }
I terminalfönstret paketerar du Webb-API:t som är redo att distribueras till Azure.
dotnet publish -c Release -o ./publish
Med det här kommandot sparas paketerade filer i en mapp med namnet Publicera.
I Visual Studio Code, högerklicka på mappen publicera och välj Distribuera till webbappen.
Välj namnet på webbprogrammet du skapade tidigare i steg 4 (<webapp name>). I följande exempel heter webbprogrammet my-fieldengineer-webapp.
Vid uppmaningen i dialogrutan Visual Studio Code, välj distribuera för att acceptera varningen och distribuera webbappen.
Kontrollera att webbprogrammet har distribuerats och gå sedan till webbplatsen.
Webbplatsen öppnas i ett nytt webbläsarfönster, men ett HTTP 404-fel visas (hittades inte). Detta beror på att webb-API-åtgärderna är tillgängliga via api-slutpunkt i stället för roten på webbplatsen. Ändra URL:en till https://<webapp name>.azurewebsites.net/api/BoilerParts. Detta URI aktiverar metoden GetBoilerParts i kontrollanten BoilerParts. Webb-API:t bör svara med ett JSON-dokument med en lista över alla exempeldelar i InventoryDB-databasen.
Ändra URL:en i webbläsaren till https://<webapp name>.azurewebsites.net/swagger. Swagger-API:et ska visas. Det här är ett grafiskt användargränssnitt som gör att en utvecklare kan verifiera och testa samtliga åtgärder i ett webb-API. Den fungerar också som ett användbart dokumentationsverktyg.
Välj GET angränsande till /api/BoilerParts/{id} slutpunkt och välj Prova.
I fältet id ange ID för en del och välj Kör. Denna åtgärd kallas metoden GetBoilerPart(long id) i kontrollanten BoilerParts. Ett JSON-dokument returneras med information om delen eller ett HTTP 404-fel om ingen matchande del hittas i databasen.
Stäng webbläsaren och återgå till Visual Studio Code.
Skapa och distribuera webb-API: Fältkunskapsbas
Fältkunskapsbaserade operationer i Webb-API fungerar på tre tabeller i KnowledgeDB databas: Tips, BoilerParts och Tekniker. Följande bild visar förhållandena mellan dessa tabeller och kolumnerna de innehåller.
Kiana använde en liknande metod för databasen Fältkunskapsbas som användes för databasen för fältlagerhantering, och utförde följande uppgifter:
Skapa C# modellklasser som återspeglar strukturen för tabellen Tips, BoilerParts och Tekniker i databasen KnowledgeDB. Koden för var och en av dessa klasser visas i följande.
Anteckning
Tabellen BoilerParts i databasen KnowledgeDB skiljer sig från tabellen BoilerParts i databasen InventoryDB. För att undvika problem med namn har modellklasser för tabeller i databasen KnowledgeDB prefixet 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; } } }
Anteckning
Tekniker Id är en sträng, inte en siffra. Detta beror på att de befintliga systemen använder GUID till identitetstekniker och andra användare.
// 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; } } }
Skapa en annan kontext för Entity Framework som webb-API använder för att ansluta till databasen 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; } } }
Redigera filen appsettings.Development.json för projektet och lägg till följande anslutningssträng KnowledgDB till avsnittet ConnectionStrings. Ersätt <server name> med namnet på SQL Database-servern som du skapade för att lagra KnowledgeDB-databasen.
{ "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": { ... } } }
Viktigt
I den här guiden finns endast anslutningssträngen användar-ID och lösenord för databasen. I ett produktionssystem bör du aldrig lagra objekten i klartext i en konfigurationsfil.
Redigera filen Startup.cs och i metoden ConfigureServices lägger du till följande instruktioner.
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(); ... }
Den andra instruktionen styr hur data serialiseras när de hämtas. Vissa av modellklasser har referenser till andra modellklasser, vilket i sin tur kan hänvisa till ytterligare modellklasser. Vissa av dessa referenser kan resultera i rekursiva loopar (Entitet A refererar till Entitet B, som refererar tillbaka till Entitet A, som refererar till Entitet B igen och så vidare). Alternativet ReferenceLoopHandling gör att serialiseraren ignorerar sådana loopar i data och en entitet och objekten som den omedelbart refererar till returneras, men inte längre.
I fönstret Terminal kör följande kommando för att generera kontrollanter från modellklasserna KnowledgeBaseBoilerTip, KnowledgeBaseBoilerPart och KnowledgeBaseEngineer och kontextklassen 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 Controllers
Alla tre kontrollanter ska skapas i mappen Kontrollanter.
Redigera filen KnowledgeBaseBoilerPartController.cs. Den här filen innehåller koden för KnowledgeBaseBoilerPart kontrollant. Den ska följa samma mönster som klassen BoilerPartsController som skapades tidigare, med REST-metoder som gör att en klient kan lista, fråga, infoga, uppdatera och ta bort entiteter. Lägg till följande metod för GetTipsForPart till kontrollanten.
[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(); } ... }
Med den här metoden returneras alla kunskapsbastips som refererar till en angiven del. Den frågar tabellen Tips i databasen via objektet KnowledgeBaseContext för att hitta den här informationen.
Redigera fileb KnowledgeBaseEngineerController.cs och lägg till följande metoder i klassen 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(); } ... }
Med metoden GetTipsForEngineer hittar du alla kunskapsbastips som har lagts upp av den angivna teknikern.
I fönstret Terminal sammanställer och bygger du webb-API.
dotnet build
Webb-API ska skapas utan att det rapporterar några fel eller varningar.
Redigera filen appSettings.json och lägg till anslutningssträngen för databasen KnowledgeDB. Den här strängen ska vara samma som du tidigare skrev till filen 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": "*" }
I fönstret Terminal paketerar du Webb-API:t som är redo att distribueras till Azure.
dotnet publish -c Release -o ./publish
I Visual Studio Code, högerklicka på mappen publicera och välj Distribuera till webbappen. Distribuera till samma Azure-webbapp som du skapade tidigare. Tillåt att guiden skriver över den befintliga webbprogrammet med den nya koden.
När distributionen är klar går du till webbplatsen men ändrar URL:en i webbläsaren till https://<webapp name>.azurewebsites.net/swagger. Åtgärderna för kontrollanterna KnowledgeBaseBoilerPart, KnowledgeBaseEngineer och KnowldgeBaseTip bör anges i åtgärderna BoilerParts. Kontrollera att åtgärderna KnowledgeBaseBoilerPart inkluderar en åtgärd för GET för URI /api/KnowledgeBaseBoilerPart/{id}/Tips och att åtgärderna KnowledgeBaseEngineer inkluderar en åtgärd för GET för URI /api/KnowledgeBaseEngineer/{id}/Tips.
Skapa och distribuera webb-API: Fältschemaläggning
Åtgärder för fältschemaläggning använder tabellerna Appointments, AppointmentStatuses (det här är en enkel uppslagstabell med värdena för giltig status för avtalad tid), Kunder och Tekniker, som visas i följande bild. Dessa tabeller lagras i SchedulesDB-databasen.
För att skapa webb-API-åtgärder för fältschemaläggningsdelen i systemet utförde Kiana följande uppgifter:
Skapa# modellklasser som återspeglar strukturen för tabellen AppointmentStatus, Avtalade tider, Kunder och Tekniker i databasen SchedulesDB. Följande kod visar var och en av dessa klasser.
Anteckning
Modellklassen för tabellen Tekniker heter ScheduleEngineer för att särskilja den från modellen för tabellen Tekniker databasen 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; } } }
Skapa en kontext för Entity Framework som webb-API använder för att ansluta till databasen 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; } } }
Redigera filen appsettings.Development.json för projektet och lägg till följande anslutningssträng SchedulesDB till avsnittet ConnectionStrings. Ersätt <server name> med namnet på SQL Database-servern som du skapade för att lagra KnowledgeDB-databasen.
{ "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": { ... } } }
Redigera filen Startup.cs och i metoden ConfigureServices lägger du till följande instruktioner.
public void ConfigureServices(IServiceCollection services) { services.AddDbContext<InventoryContext>...; services.AddDbContex\<KnowledgeBaseContext>...; services.AddDbContext<ScheduleContext>(options => options.UseSqlServer(Configuration.GetConnectionString("SchedulesDB"))); services.AddControllers().AddNewtonsoftJson(...); ... }
I fönstret Terminal kör följande kommando för att generera kontrollanter från modellklasserna Avtalad tid, Kund och ScheduleEngineer och kontextklassen ScheduleContext.
Anteckning
Skapa inte en separat kontrollant för AppointmentStatus-modellen.
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 Controllers
Redigera filen AppointmentsController.cs. I klassen AppointmentsController hitta metoden GetAppointments. Ändra instruktionen retur enligt vad som visas. Den här ändringen säkerställer att informationen om Kund, Tekniker och AppointmentStatus hämtas som en del av åtgärden GET. Dessa fält refererar till andra entiteter som annars lämnas null på grund av Entity Framework inläsningsmekanism.
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(); } ... }
I samma fil ändrar du metoden GetAppointment(long id) enligt bilden.
// 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; }
Den här versionen av metoden fyller i fälten Kund, Tekniker och AppointmentStatus för en avtalad tid när den hämtas (om den läses in lämnar dessa fält tomma annars).
Hitta PutAppointment-metoden och ersätt den med följande kod. I den här versionen av metoden PutAppointment använder fälten i en avtalad tid som en användare kan ändra i programmet snarare än slutför objektet Avtalad tid.
[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(); }
Anteckning
Som en allmän regel bör PUT-åtgärder endast ändra data som en användare ska kunna uppdatera, inte bara alla fält i en entitet.
Öppna filen ScheduleEngineerController.cs och lägg till följande metod GetScheduleEngineerAppointments i klassen 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(); } ... }
Metoden GetAppointments hittar alla avtalade tider för den angivna kunden. Metoden GetNotes hämtar alla anteckningar teknikern gjorde vid tidigare besök till kunden.
Redigera filen appSettings.json och lägg till anslutningssträngen för databasen KnowledgeDB. Den här strängen ska vara samma som du tidigare skrev till filen 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": "*" }
I fönstret Terminal sammanställer och bygger du webb-API.
dotnet build
Webb-API ska skapas utan att det rapporterar några fel eller varningar.
I fönstret Terminal paketerar du Webb-API:t som är redo att distribueras till Azure.
dotnet publish -c Release -o ./publish
I Visual Studio Code, högerklicka på mappen publicera och välj Distribuera till webbappen. Distribuera till samma Azure-webbapp som du skapade tidigare. Tillåt att guiden skriver över den befintliga webbprogrammet med den nya koden.
När distributionen är klar går du till webbplatsen men ändrar URL:en i webbläsaren till https://<webapp name>.azurewebsites.net/swagger. Kontrollera att åtgärderna för kontrollanterna Avtalade tider, Kund och ScheduleEngineer nu är tillgängliga.
Webb-API:et är nu redo att ingå i programmet.