แชร์ผ่าน


บทที่ 5: การสร้างและการเผยแพร่ Web API ใน Azure

เมื่อพิจารณาแล้วว่าข้อมูลสำหรับแอปของช่างเทคนิคควรมาจากระบบที่มีอยู่ผ่าน Web API นั้น Maria และ Kiana จึงทำงานร่วมกันเพื่อพิจารณาว่าข้อมูลใดที่ต้องการ และอยู่ในรูปแบบใด จากนั้น Kiana จะสร้างเว็บแอปที่เปิดเผย Web API ที่เหมาะสม และจัดเตรียมให้มีการโฮสต์ใน Azure แอปสามารถเชื่อมต่อกับ Azure ได้จากทุกที่ที่มีการเชื่อมต่อแบบไร้สาย

การกำหนดการดำเนินการ Web API: การจัดการสินค้าคงคลังภาคสนาม

หน้าจอ เรียกดู ของส่วนการจัดการสินค้าคงคลังภาคสนามของแอป จะแสดงรายการของชิ้นส่วนสำหรับหม้อไอน้ำและระบบปรับอากาศ (เรียกง่ายๆ ว่า ชิ้นส่วนหม้อไอน้ำ) หน้าจอ รายละเอียด ช่วยให้ช่างเทคนิคสามารถดูข้อมูลเพิ่มเติมเกี่ยวกับชิ้นส่วนที่เลือกได้

ในฐานข้อมูลสินค้าคงคลังที่มีอยู่ (ที่ชื่อว่า InventoryDB) ข้อมูลเกี่ยวกับชิ้นส่วนจะถูกเก็บไว้ในตารางเดียวที่มีชื่อว่า BoilerParts Kiana กำหนดว่า Web API ควรรองรับคำขอต่อไปนี้:

  • รับชิ้นส่วนหม้อไอน้ำทั้งหมด
  • รับรายละเอียดของชิ้นส่วน โดยระบุรหัสชิ้นส่วน

การกำหนดการดำเนินการ Web API: ฐานข้อมูลองค์ความรู้ภาคสนาม

ในระบบที่มีอยู่ ฐานข้อมูลองค์ความรู้ (ที่ชื่อว่า KnowledgeDB) ประกอบด้วยตารางสามตารางที่บันทึกและจัดการความสัมพันธ์ในเคล็ดลับ วิศวกร และชิ้นส่วนต่างๆ:

  • เคล็ดลับ ซึ่งมีรายละเอียดของเคล็ดลับ เคล็ดลับแต่ละข้อประกอบด้วยสรุปแบบบรรทัดเดียวที่ระบุปัญหาเฉพาะ (เรื่อง) และคำอธิบายโดยละเอียดเพิ่มเติมซึ่งอธิบายวิธีการแก้ปัญหา (เนื้อความ) นอกจากนี้ เคล็ดลับแต่ละข้อยังอ้างอิงถึงชิ้นส่วนและวิศวกรที่บันทึกเคล็ดลับ
  • BoilerParts ซึ่งมีรายการของชิ้นส่วนที่อ้างอิงโดยเคล็ดลับ รายละเอียดของชิ้นส่วนนั้นจะถูกเก็บไว้ในตาราง BoilerParts ในฐานข้อมูล InventoryDB
  • วิศวกร ซึ่งแสดงรายชื่อช่างเทคนิคที่เป็นผู้เขียนเคล็ดลับแต่ละข้อ

ขณะนี้ส่วนฐานข้อมูลองค์ความรู้ของแอปมีเพียงหน้าจอ เบราว์เซอร์ ของตัวยึดตำแหน่ง Maria ต้องการใช้ฟังก์ชันต่อไปนี้:

  • ช่างเทคนิคระบุคำที่ใช้ค้นหาบนหน้าจอ เรียกดู เพื่อค้นหาเคล็ดลับที่ตรงกันทั้งหมด การจับคู่อาจอยู่ในชื่อของส่วนที่ปลายอ้างอิงถึง ข้อความในหัวเรื่องหรือเนื้อหาของเคล็ดลับ หรือชื่อของช่างเทคนิคที่เป็นผู้เชี่ยวชาญที่มีอุปกรณ์เฉพาะ

  • เมื่อพบเคล็ดลับที่ตรงกันทั้งหมด ช่างเทคนิคสามารถเลือกเคล็ดลับเพื่อดูรายละเอียดได้

  • นอกจากนี้ ช่างเทคนิคยังสามารถเพิ่มเคล็ดลับใหม่ๆ ในฐานข้อมูลองค์ความรู้ รวมทั้งเพิ่มบันทึกย่อและความคิดเห็นในเคล็ดลับที่มีอยู่

    ฐานข้อมูลองค์ความรู้มีขนาดใหญ่และเติบโตขึ้น และการสืบค้นในหลายๆ ตารางและหลายๆ คอลัมน์ อาจเกี่ยวข้องกับตรรกะที่ซับซ้อนซึ่งต้องใช้พลังในการประมวลผลอย่างมาก เพื่อลดโหลดบน Web API Kiana ตัดสินใจใช้ Azure Cognitive Search เพื่อจัดเตรียมฟังก์ชันการค้นหา ดังที่อธิบายไว้ก่อนหน้านี้ เพื่อสนับสนุนแอป Kiana ตัดสินใจว่าการดำเนินการต่อไปนี้จำเป็นต้องใช้จาก Web API:

  • ค้นหารายละเอียดของเคล็ดลับฐานข้อมูลองค์ความรู้ที่ระบุจากตาราง เคล็ดลับ

  • อัปเดตเคล็ดลับฐานข้อมูลองค์ความรู้ที่มีอยู่ในตาราง เคล็ดลับ

  • เพิ่มเคล็ดลับฐานข้อมูลองค์ความรู้ใหม่ในตาราง เคล็ดลับ ซึ่งอาจเกี่ยวข้องกับการเพิ่มแถวในตาราง BoilerParts และตาราง วิศวกร หากชิ้นส่วนหรือวิศวกรที่ระบุในขณะนี้ไม่มีเคล็ดลับที่บันทึกไว้ งานประจำที่ดำเนินการตรรกะเบื้องหลังการเพิ่มเคล็ดลับใหม่ จะถูกนำไปใช้เป็นแอปตรรกะที่เรียกมาจาก Power Apps

การกำหนดการดำเนินการ Web API: การจัดกำหนดการภาคสนาม

การจัดกำหนดการนัดหมายช่างเทคนิคไม่เพียงต้องการการสอบถาม การเพิ่ม และการลบการนัดหมายเท่านั้น แต่ยังต้องบันทึกข้อมูลเกี่ยวกับลูกค้าด้วย ระบบการนัดหมายที่มีอยู่จะบันทึกข้อมูลนี้ในตารางสามตารางในฐานข้อมูล SchedulesDB:

  • การนัดหมาย ซึ่งมีรายละเอียดของการนัดหมายแต่ละครั้ง ซึ่งรวมถึงวันที่ เวลา ปัญหา บันทึกย่อ และช่างเทคนิคที่ได้รับมอบหมายให้ทำงาน
  • ลูกค้า ซึ่งเก็บรายละเอียดของลูกค้าแต่ละราย ซึ่งรวมถึงชื่อ ที่อยู่ และรายละเอียดการติดต่อ
  • วิศวกร ซึ่งแสดงรายชื่อช่างแต่ละคนที่เข้าร่วมการนัดหมาย

หมายเหตุ

ฐานข้อมูลมีตารางที่สี่ที่ชื่อว่า AppointmentsStatus ตารางนี้ประกอบด้วยรายการของค่าที่ถูกต้องสำหรับสถานะของการนัดหมาย และเป็นเพียงการค้นหาที่ใช้โดยส่วนอื่นๆ ของระบบการนัดหมายที่มีอยู่

Kiana ตัดสินใจว่าการดำเนินการต่อไปนี้จะเป็นประโยชน์สำหรับส่วนการจัดกำหนดการภาคสนามของแอป:

  • ค้นหาการนัดหมายทั้งหมดสำหรับช่างเทคนิคที่ระบุ
  • ค้นหาการนัดหมายทั้งหมดสำหรับวันปัจจุบันสำหรับช่างเทคนิคที่ระบุ
  • ค้นหาการนัดหมายตามกำหนดการถัดไปสำหรับช่างเทคนิคที่ระบุ
  • อัปเดตรายละเอียดของการนัดหมาย เช่น การเพิ่มบันทึกย่อหรือรูปถ่าย
  • ค้นหารายละเอียดเกี่ยวกับลูกค้า

การสร้าง Web API: การจัดการสินค้าคงคลังภาคสนาม

ระบบที่มีอยู่จัดเก็บข้อมูลโดยใช้ฐานข้อมูล Azure SQL Kiana ตัดสินใจที่จะสร้าง Web API โดยใช้ Entity Framework Core เนื่องจากวิธีนี้สามารถสร้างโค้ดจำนวนมากเพื่อสอบถาม แทรก และอัปเดตข้อมูลโดยอัตโนมัติ เทมเพลต Web API ที่ Microsoft จัดเตรียมไว้ให้ ยังสามารถสร้าง Description ของ Swagger ที่อธิบายการดำเนินการแต่ละอย่างใน API Description เหล่านี้มีประโยชน์สำหรับการทดสอบการดำเนินงานของ API เครื่องมือจำนวนมากสามารถใช้ข้อมูลนี้เพื่อรวม API กับบริการอื่นๆ เช่น Azure API Management

Kiana เริ่มต้นด้วยฟังก์ชัน Field Inventory เนื่องจากเป็นส่วนที่ตรงไปตรงมาที่สุด การดำเนินการของ Field Inventory ใน Web API จะสอบถามตารางเดียว BoilerParts ในฐานข้อมูล InventoryDB ตารางนี้มีคอลัมน์ที่แสดงในภาพต่อไปนี้

ตาราง BoilerParts ที่แสดงคอลัมน์รหัส, ชื่อ, CategoryId, ราคา, ภาพรวม, NumberInStock และ ImageURL

Kiana ใช้แนวทาง "code-first" ในการสร้าง Web API และทำสิ่งต่อไปนี้

  1. กำหนดคลาสโมเดล C# ที่จำลองโครงสร้างของตาราง BoilerParts ในฐานข้อมูล InventoryDB

  2. สร้างคลาส บริบท ของ Entity Framework ที่ Web API ใช้เพื่อเชื่อมต่อกับฐานข้อมูล เพื่อดำเนินการสืบค้น

  3. ตั้งค่าคอนฟิกคลาสบริบทเพื่อเชื่อมต่อกับฐานข้อมูล InventoryDB ใน Azure

  4. ใช้เครื่องมือบรรทัดคำสั่ง Entity Framework เพื่อสร้างคลาส ตัวควบคุม ของ Web API ที่ใช้คำขอ HTTP REST สำหรับแต่ละการดำเนินการที่สามารถดำเนินการเทียบกับตาราง BoilerParts

  5. ใช้ Swagger API เพื่อทดสอบ Web API

ภาพต่อไปนี้แสดงโครงสร้างระดับสูงของ Web API

โครงสร้างระดับสูงของ Inventory Web API

Kiana ใช้กระบวนงานต่อไปนี้เพื่อสร้าง Web API โดยใช้เครื่องมือบรรทัดคำสั่ง .NET 6.0 และ Visual Studio Code:

  1. เปิดหน้าต่างเทอร์มินัลนี้ใน Visual Studio Code

    หน้าต่างเทอร์มินัลใหม่ใน VS Code

  2. รันคำสั่งต่อไปนี้เพื่อสร้างโครงการ Web API ใหม่ที่ชื่อว่า FieldEngineerApi

    dotnet new webapi -o FieldEngineerApi
    
  3. เปิดโฟลเดอร์ FieldEngineerApi

    เปิดโฟลเดอร์ FieldEngineerApi

  4. ลบตัวควบคุม WeatherForecastController.cs และไฟล์คลาส WeatherForecast.cs ตัวอย่าง ที่สร้างโดยเทมเพลต Web API

    ลบไฟล์ WeatherForecast

  5. ในหน้าต่าง เทอร์มินัล เพิ่มแพ็กเกจและเครื่องมือ Entity Framework ต่อไปนี้ พร้อมกับการสนับสนุนสำหรับการใช้ 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-codegenerator
    
  6. ในโฟลเดอร์ FieldEngineerApi สร้างโฟลเดอร์ใหม่ที่ชื่อว่า โมเดล

    โฟลเดอร์สร้างโมเดล

  7. ในโฟลเดอร์โมเดล ให้สร้างไฟล์โค้ด C# ที่ชื่อ BoilerPart.cs

    สร้างคลาส BoilerPart

  8. ในไฟล์นี้ ให้เพิ่มคุณสมบัติและฟิลด์ต่อไปนี้ คุณสมบัติและฟิลด์เหล่านี้สะท้อนโครงสร้างของตาราง BoilerParts ในฐานข้อมูล 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; }
        }
    }
    
  9. ในโฟลเดอร์ โมเดล ให้สร้างไฟล์โค้ด C# อีกไฟล์ที่ชื่อ InventoryContext.cs เพิ่มรหัสต่อไปนี้ในคลาสนี้ คลาสจัดเตรียมการเชื่อมต่อระหว่างตัวควบคุม (ที่จะสร้างถัดไป) และฐานข้อมูล

    using Microsoft.EntityFrameworkCore;
    
    namespace FieldEngineerApi.Models
    {
        public class InventoryContext : DbContext
        {
            public InventoryContext(DbContextOptions<InventoryContext> options)
                : base(options)
            {
    
            }
    
            public DbSet\<BoilerPart\> BoilerParts { get; set; }
        }
    }
    
  10. แก้ไขไฟล์ appsettings.Development.json สำหรับโครงการ และเพิ่มส่วน ConnectionStrings ด้วยสตริงการเชื่อมต่อ InventoryDB ต่อไปนี้ แทนที่ <server name> ด้วยชื่อของเซิร์ฟเวอร์ฐานข้อมูล SQL ที่คุณสร้างขึ้นเพื่อเก็บฐานข้อมูล 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"
            }
        }
    }
    

    สำคัญ

    สำหรับวัตถุประสงค์ของคู่มือนี้เท่านั้น สตริงการเชื่อมต่อประกอบด้วย ID ผู้ใช้และรหัสผ่านสำหรับฐานข้อมูล ในระบบการใช้งานจริง คุณไม่ควรเก็บรายการเหล่านี้เป็นข้อความที่ชัดเจนในไฟล์การตั้งค่าคอนฟิก

  11. แก้ไขไฟล์ Startup.cs และเพิ่มคำสั่ง โดยใช้ ต่อไปนี้ไปยังรายการที่จุดเริ่มต้นของไฟล์

    using FieldEngineerApi.Models;
    using Microsoft.EntityFrameworkCore;
    
  12. ในคลาส เริ่มต้น ค้นหาวิธี ConfigureServices เพิ่มคำสั่งต่อไปนี้ในวิธีนี้

    public void ConfigureServices(IServiceCollection services)
    {
    
        services.AddDbContext<InventoryContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("InventoryDB")));
    
        services.AddControllers();
        ...
    }
    
  13. แก้ไขวิธีการ ตั้งค่าคอนฟิก และเปิดใช้งาน Swagger UI แม้ว่าแอปจะทำงานในโหมดการใช้งานจริง ดังที่แสดง (การเปลี่ยนแปลงนี้เกี่ยวข้องกับการย้ายตำแหน่งการเรียกวิธีการ app.UseSwagger ทั้งสองรายการภายนอกคำสั่ง ถ้า)

    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"));
    
        ...
    }
    

    สำคัญ

    การเปลี่ยนแปลงนี้ทำให้สามารถเปิดเผยจุดสิ้นสุดของ Swagger สำหรับการรวมการจัดการ API หลังจากตั้งค่าคอนฟิกการจัดการ API แล้ว คุณควรย้ายรหัสนี้กลับเข้าไปภายในคำสั่ง ถ้า และปรับใช้ Web API อีกครั้ง อย่าปล่อยให้จุดสิ้นสุดของ Swagger เปิดไว้ในระบบการใช้งานจริง

  14. ในหน้าต่าง เทอร์มินัล เรียกใช้คำสั่งต่อไปนี้เพื่อสร้างตัวควบคุม BoilerParts จากคลาสโมเดล BoilerPart และคลาสบริบท InventoryContext

    dotnet aspnet-codegenerator controller ^
        -name BoilerPartsController -async -api ^
         -m BoilerPart -dc InventoryContext -outDir Controllers
    

    ควรสร้างตัวควบคุม BoilerParts ในโฟลเดอร์ ตัวควบคุม

    [!หมายเหตุ] อักขระตัวกําหนดบรรทัด ^ ได้รับการยอมรับโดย Windows เท่านั้น หากคุณกำลังเรียกใช้ Visual Studio Code บนระบบ Linux ให้ใช้อักขระ \ แทน

  15. เปิดไฟล์ BoilerParts.cs ในโฟลเดอร์ ตัวควบคุม และตรวจสอบเนื้อหา คลาส BoilerPartsController แสดงวิธีการ REST ต่อไปนี้:

    • GetBoilerParts() ซึ่งส่งคืนรายการของวัตถุ BoilerPart ทั้งหมดจากฐานข้อมูล
    • GetBoilerPart(long id) ซึ่งดึงรายละเอียดของชิ้นส่วนหม้อไอน้ำที่ระบุ
    • PutBoilerPart(long id, BoilerPart boilerPart) ซึ่งอัปเดตชิ้นส่วนหม้อไอน้ำในฐานข้อมูลพร้อมรายละเอียดในวัตถุ BoilerPart ที่ระบุเป็นพารามิเตอร์
    • PostBoilerPart(BoilerPart boilerPart) ซึ่งสร้างชิ้นส่วนหม้อไอน้ำใหม่
    • DeleteBoilerPart(long id) ซึ่งลบชิ้นส่วนหม้อไอน้ำที่ระบุจากฐานข้อมูล

    หมายเหตุ

    แอปของช่างเทคนิคต้องการวิธีการ รับ เพียงสองวิธี แต่วิธีอื่นมีประโยชน์สำหรับแอปการจัดการสินค้าคงคลังบนเดสก์ท็อป (ซึ่งไม่ครอบคลุมในคู่มือนี้)

  16. รวบรวมและสร้าง Web API

    dotnet build
    

Web API ควรสร้างโดยไม่ต้องรายงานข้อผิดพลาดหรือคำเตือนใดๆ

การปรับใช้ Web API กับ Azure: การจัดการสินค้าคงคลังภาคสนาม

Kiana ปรับใช้และทดสอบ Web API โดยดำเนินงานต่อไปนี้:

  1. โดยใช้ส่วนขยายบัญชี Azure ใน Visual Studio Code ให้ลงชื่อเข้าใช้การสมัครใช้งาน Azure ของคุณ

  2. จากหน้าต่างเทอร์มินัลใน Visual Studio Code สร้างกลุ่มทรัพยากรใหม่ที่ชื่อว่า webapi_rg ในการสมัครใช้งาน Azure ของคุณ ในคำสั่งต่อไปนี้ แทนที่ <location> ด้วยภูมิภาค Azure ที่ใกล้ที่สุดของคุณ

    az group create ^
        --name webapi_rg ^
        --location <location>
    
  3. สร้างแผน Azure App Service เพื่อจัดหาทรัพยากรสำหรับการโฮสต์ Web API

    az appservice plan create ^
        --name webapi_plan ^
        --resource-group webapi_rg ^
        --sku F1
    

    หมายเหตุ

    F1 คือ SKU ฟรีสำหรับแผน App Service ซึ่งให้ปริมาณงานและกำลังการผลิตที่จำกัด และเหมาะสำหรับวัตถุประสงค์ในการพัฒนาเท่านั้น

  4. สร้างเว็บแอป Azure โดยใช้แผน App Service แทนที่ <webapp name> ด้วยชื่อเฉพาะสำหรับเว็บแอป

    az webapp create ^
        --name <webapp name> ^
        --resource-group webapi_rg ^
        --plan webapi_plan
    
  5. ใน Visual Studio Code แก้ไขไฟล์ appSettings.json และเพิ่มสตริงการเชื่อมต่อเดียวกันกับที่คุณเคยเขียนไว้ในไฟล์ appSettings.Development.json โปรดอย่าลืมแทนที่ <server name> ด้วยชื่อของเซิร์ฟเวอร์ฐานข้อมูล SQL ที่คุณสร้างขึ้นเพื่อเก็บฐานข้อมูล 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": "*"
    }
    
  6. ในหน้าต่างเทอร์มินัล ให้จัดแพคเกจ Web API ให้พร้อมสำหรับการปรับใช้กับ Azure

    dotnet publish -c Release -o ./publish
    

    คำสั่งนี้บันทึกไฟล์แบบรวมแพคเกจไปยังโฟลเดอร์ที่ชื่อว่า เผยแพร่

  7. ใน Visual Studio Code คลิกขวาที่โฟลเดอร์ เผยแพร่ แล้วเลือก ปรับใช้กับ Web App

    ปรับใช้เว็บแอปจาก VS Code

  8. เลือกชื่อของเว็บแอปที่คุณสร้างไว้ก่อนหน้านี้ในขั้นตอนที่ 4 (<webapp name>) ในตัวอย่างต่อไปนี้ เว็บแอปมีชื่อว่า my-fieldengineer-webapp

    เลือกเว็บแอป

  9. ที่พร้อมท์ในกล่องโต้ตอบ Visual Studio Code เลือก ปรับใช้ เพื่อยอมรับคำเตือนและปรับใช้เว็บแอป

    คำเตือนการปรับใช้ VS Code

  10. ตรวจสอบว่าเว็บแอปถูกปรับใช้งานได้สำเร็จ และจากนั้น เรียกดูเว็บไซต์

    เรียกดูกล่องโต้ตอบเว็บไซต์ใน VS Code

  11. เว็บไซต์จะเปิดขึ้นในหน้าต่างเบราว์เซอร์ใหม่ แต่จะแสดงข้อผิดพลาด HTTP 404 (ไม่พบ) เนื่องจากการดำเนินงานของ Web API พร้อมใช้งานผ่านทางจุดสิ้นสุด api แทนที่จะเป็นรากของเว็บไซต์ เปลี่ยน URL เป็น https://<webapp name>.azurewebsites.net/api/BoilerParts URI นี้เรียกใช้วิธีการ GetBoilerParts ในตัวควบคุม BoilerParts Web API ควรตอบสนองด้วยเอกสาร JSON ที่แสดงรายการชิ้นส่วนหม้อไอน้ำทั้งหมดในฐานข้อมูล InventoryDB

    รายการชิ้นส่วนที่แสดงในเว็บเบราว์เซอร์

  12. เปลี่ยน URL ในเบราว์เซอร์เป็น https://<webapp name>.azurewebsites.net/swagger Swagger API ควรปรากฏขึ้น นี่คือส่วนติดต่อผู้ใช้แบบกราฟิกที่ช่วยให้นักพัฒนาสามารถตรวจสอบและทดสอบการดำเนินการแต่ละอย่างใน Web API นอกจากนี้ ยังทำหน้าที่เป็นเครื่องมือคู่มือที่มีประโยชน์

    Swagger UI ที่แสดงรายการของการดำเนินการ

  13. เลือก GET ที่ติดกับจุดสิ้นสุด /api/BoilerParts/{id} แล้วจากนั้น เลือก ลองใช้งาน

    หน้าจอ

  14. ในฟิลด์ id ป้อน ID ของชิ้นส่วน และจากนั้น เลือก ดำเนินการ การดำเนินการนี้เรียกใช้วิธีการ GetBoilerPart(long id) ในตัวควบคุม BoilerParts ซึ่งจะส่งคืนเอกสาร JSON พร้อมรายละเอียดของชิ้นส่วนหรือข้อผิดพลาด HTTP 404 หากไม่พบชิ้นส่วนที่ตรงกันในฐานข้อมูล

    การตอบสนองใน Swagger UI

  15. ปิดเว็บเบราว์เซอร์แล้วกลับไปที่ Visual Studio Code

การสร้างและการปรับใช้ Web API: ฐานข้อมูลองค์ความรู้ภาคสนาม

การดำเนินการฐานข้อมูลองค์ความรู้ใน Web API ทำงานกับตารางสามตารางในฐานข้อมูล KnowledgeDB: คำแนะนำ, BoilerParts และ Engineers ภาพต่อไปนี้แสดงความสัมพันธ์ระหว่างตารางเหล่านี้และคอลัมน์ที่มี

ความสัมพันธ์ของตารางฐานข้อมูลองค์ความรู้

Kiana นำแนวทางที่คล้ายกันมาใช้กับฐานข้อมูลของฐานข้อมูลองค์ความรู้ภาคสนามที่เธอใช้สำหรับฐานข้อมูล Field Inventory Management และทำงานต่อไปนี้

  1. สร้างคลาสโมเดล C# ที่จำลองโครงสร้างของตาราง เคล็ดลับ, BoilerParts และ วิศวกร ในฐานข้อมูล KnowledgeDB รหัสสำหรับคลาสเหล่านี้แต่ละคลาสจะแสดงดังต่อไปนี้

    หมายเหตุ

    ตาราง BoilerParts ในฐานข้อมูล KnowledgeDB แตกต่างจากตาราง BoilerParts ในฐานข้อมูล InventoryDB เพื่อหลีกเลี่ยงการไม่กลมกลืนกันของชื่อ คลาสโมเดลสำหรับตารางในฐานข้อมูล KnowledgeDB มีคำนำหน้า 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; }
        }
    }
    

    หมายเหตุ

    Id ของวิศวกรเป็นสตริง ไม่ใช่ตัวเลข เนื่องจากระบบที่มีอยู่ใช้ GUID เพื่อระบุตัวตนช่างเทคนิคและผู้ใช้รายอื่น

    // 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; }
        }
    }
    
  2. สร้างคลาส บริบท ของ Entity Framework อื่นที่ Web API ใช้เพื่อเชื่อมต่อกับฐานข้อมูล 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; }
        }
    }
    
  3. แก้ไขไฟล์ appsettings.Development.json สำหรับโครงการ และเพิ่มส่วนการเชื่อมต่อ KnowledgDB ต่อไปนี้ไปยังส่วน ConnectionStrings แทนที่ <server name> ด้วยชื่อของเซิร์ฟเวอร์ฐานข้อมูล SQL ที่คุณสร้างขึ้นเพื่อเก็บฐานข้อมูล 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": {
            ...
            }
        }
    }
    

    สำคัญ

    สำหรับวัตถุประสงค์ของคู่มือนี้เท่านั้น สตริงการเชื่อมต่อประกอบด้วย ID ผู้ใช้และรหัสผ่านสำหรับฐานข้อมูล ในระบบการใช้งานจริง คุณไม่ควรเก็บรายการเหล่านี้เป็นข้อความที่ชัดเจนในไฟล์การตั้งค่าคอนฟิก

  4. แก้ไขไฟล์ Startup.cs ไฟล์ และในวิธีการ ConfigureServices เพิ่มคำสั่งต่อไปนี้

    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();
        ...
    }
    

    คำสั่งที่สองควบคุมวิธีการจัดลำดับข้อมูลเมื่อมีการดึงข้อมูล คลาสโมเดลบางคลาสมีการอ้างอิงคลาสโมเดลอื่นๆ ซึ่งสามารถอ้างอิงคลาสโมเดลเพิ่มเติมได้ การอ้างอิงเหล่านี้บางส่วนอาจทำให้เกิดการวนซ้ำได้ (เอนทิตี A อ้างอิงเอนทิตี B ซึ่งอ้างอิงกลับไปยังเอนทิตี A ซึ่งอ้างอิงเอนทิตี B อีกครั้ง ไปเรื่อยๆ) ตัวเลือก ReferenceLoopHandling ทำให้ serializer เพิกเฉยต่อการวนซ้ำดังกล่าวในข้อมูล และส่งคืนเฉพาะเอนทิตีและอ็อบเจ็กต์ที่อ้างอิงทันที แต่ไม่มากกว่านั้น

  5. ในหน้าต่าง เทอร์มินัล เรียกใช้คำสั่งต่อไปนี้เพื่อสร้างตัวควบคุมจากคลาสโมเดล KnowledgeBaseBoilerTip, KnowledgeBaseBoilerPart และ KnowledgeBaseEngineer และคลาสบริบท 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
    

    ควรสร้างตัวควบคุมทั้งสามรายการในโฟลเดอร์ ตัวควบคุม

  6. แก้ไขไฟล์ KnowledgeBaseBoilerPartController.cs ไฟล์นี้มีรหัสสำหรับตัวควบคุม KnowledgeBaseBoilerPart ซึ่งควรเป็นไปตามรูปแบบเดียวกับคลาส BoilerPartsController ที่สร้างขึ้นก่อนหน้านี้ โดยเปิดเผยวิธีการ REST ที่เปิดใช้งานไคลเอ็นต์เพื่อแสดงรายการ สอบถาม แทรก อัปเดต และลบเอนทิตี เพิ่มวิธีการ GetTipsForPart ต่อไปนี้ไปยังตัวควบคุม

    [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();
        }
        ...
    }
    

    วิธีนี้ส่งคืนเคล็ดลับฐานข้อมูลองค์ความรู้ทั้งหมดที่อ้างอิงส่วนที่ระบุ ซึ่งค้นหาตาราง เคล็ดลับ ในฐานข้อมูลผ่านวัตถุ KnowledgeBaseContext เพื่อค้นหาข้อมูลนี้

  7. แก้ไขไฟล์ KnowledgeBaseEngineerController.cs และเพิ่มวิธีการต่อไปนี้ในคลาส 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();
        }
    
        ...
    }
    

    วิธีการ GetTipsForEngineer ค้นหาเคล็ดลับฐานข้อมูลองค์ความรู้ทั้งหมดที่โพสต์โดยวิศวกรที่ระบุ

  8. ในหน้าต่าง เทอร์มินัล รวบรวมและสร้าง Web API

    dotnet build
    

    Web API ควรสร้างโดยไม่ต้องรายงานข้อผิดพลาดหรือคำเตือนใดๆ

  9. แก้ไขไฟล์ appSettings.json และเพิ่มสตริงการเชื่อมต่อสำหรับฐานข้อมูล KnowledgeDB สตริงนี้ควรเป็นสตริงเดียวกับที่คุณเคยเขียนถึงไฟล์ 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": "*"
    }
    
  10. ในหน้าต่าง เทอร์มินัล ให้จัดแพคเกจ Web API ให้พร้อมสำหรับการปรับใช้กับ Azure

    dotnet publish -c Release -o ./publish
    
  11. ใน Visual Studio Code คลิกขวาที่โฟลเดอร์ เผยแพร่ แล้วเลือก ปรับใช้กับ Web App ปรับใช้กับเว็บแอป Azure เดียวกับที่คุณสร้างไว้ก่อนหน้านี้ อนุญาตให้วิซาร์ดเขียนทับเว็บแอปที่มีอยู่ด้วยรหัสใหม่

  12. เมื่อการปรับใช้งานเสร็จสิ้น ให้เรียกดูเว็บไซต์ แต่เปลี่ยน URL ในเบราว์เซอร์เป็น https://<webapp name>.azurewebsites.net/swagger การดำเนินการสำหรับตัวควบคุม KnowledgeBaseBoilerPart, KnowledgeBaseEngineer และ KnowldgeBaseTip ควรอยู่ในรายการ นอกเหนือจากการดำเนินงาน BoilerParts ที่มีอยู่ ตรวจสอบว่าการดำเนินงาน KnowledgeBaseBoilerPart รวมถึงการดำเนินการ GET สำหรับ URI /api/KnowledgeBaseBoilerPart/{id}/Tips และการดำเนินงาน KnowledgeBaseEngineer รวมถึงการดำเนินการ รับ สำหรับ URI /api/KnowledgeBaseEngineer/{id}/Tips

    Swagger UI พร้อมการดำเนินงานใหม่

การสร้างและการปรับใช้งาน Web API: การจัดกำหนดการภาคสนาม

การดำเนินการจัดกำหนดการภาคสนามใช้ตาราง การนัดหมาย, AppointmentStatuses (นี่คือตารางการค้นหาอย่างง่ายที่แสดงค่าสถานะการนัดหมายที่ถูกต้อง) ลูกค้า และ วิศวกร ดังแสดงในภาพต่อไปนี้ ตารางเหล่านี้จะถูกเก็บไว้ในฐานข้อมูล SchedulesDB

ความสัมพันธ์ของการนัดหมายและตารางการจัดกำหนดการ

ในการสร้างการดำเนินการ Web API สำหรับส่วนการจัดกำหนดการภาคสนามของระบบ Kiana ดำเนินงานต่อไปนี้:

  1. สร้างคลาสโมเดล C# ที่จำลองโครงสร้างของตาราง AppointmentStatus, การนัดหมาย, ลูกค้า และ วิศวกร ในฐานข้อมูล SchedulesDB รหัสต่อไปนี้แสดงคลาสเหล่านี้แต่ละคลาส

    หมายเหตุ

    คลาสโมเดลสำหรับตาราง วิศวกร ถูกตั้งชื่อว่า ScheduleEngineer เพื่อแยกความแตกต่างจากโมเดลสำหรับตาราง วิศวกร ในฐานข้อมูล 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; }
        }
    }
    
  2. สร้างคลาส บริบท ของ Entity Framework ที่ Web API ใช้เพื่อเชื่อมต่อกับฐานข้อมูล 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; }
        }
    }
    
  3. แก้ไขไฟล์ appsettings.Development.json สำหรับโครงการ และเพิ่มส่วนการเชื่อมต่อ SchedulesDB ต่อไปนี้ไปยังส่วน ConnectionStrings แทนที่ <server name> ด้วยชื่อของเซิร์ฟเวอร์ฐานข้อมูล SQL ที่คุณสร้างขึ้นเพื่อเก็บฐานข้อมูล 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": {
            ...
            }
        }
    }
    
  4. แก้ไขไฟล์ Startup.cs และในวิธีการ ConfigureServices เพิ่มคำสั่งต่อไปนี้

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<InventoryContext>...;
    
        services.AddDbContex\<KnowledgeBaseContext>...;
    
        services.AddDbContext<ScheduleContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("SchedulesDB")));
    
        services.AddControllers().AddNewtonsoftJson(...);
    
        ...
    }
    
  5. ในหน้าต่าง เทอร์มินัล เรียกใช้คำสั่งต่อไปนี้เพื่อสร้างตัวควบคุมจากคลาสโมเดล การนัดหมาย, ลูกค้า และ ScheduleEngineer และคลาสบริบท ScheduleContext

    หมายเหตุ

    อย่าสร้างตัวควบคุมแยกต่างหากสำหรับโมเดล 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 Controllers
    
  6. แก้ไขไฟล์ AppointmentsController.cs ในคลาส AppointmentsController ค้นหาวิธีการ GetAppointments แก้ไขคำสั่ง ส่งคืน ดังที่แสดง การเปลี่ยนแปลงนี้ช่วยให้มั่นใจได้ว่าข้อมูล ลูกค้า, วิศวกร และ AppointmentStatus จะถูกดึงมาเป็นส่วนหนึ่งของการดำเนินการ GET ฟิลด์เหล่านี้อ้างอิงเอนทิตีอื่นๆ ที่อาจจะถูกปล่อยเป็น null เนื่องจากกลไกการโหลดที่ช้าของ 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();
        }
    
        ...
    }
    
  7. ในไฟล์เดียวกัน ให้แก้ไขวิธีการ GetAppointment(long id) ดังที่แสดง

    // 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;
    }
    

    วิธีการเวอร์ชันนี้จะเติมข้อมูลฟิลด์ ลูกค้า, วิศวกร และ AppointmentStatus ของการนัดหมาย เมื่อถูกเรียกข้อมูล (ไม่เช่นนั้น การโหลดที่ช้าจะปล่อยให้ฟิลด์เหล่านี้ว่างเปล่า)

  8. ค้นหาวิธีการ PutAppointment และแทนที่ด้วยรหัสต่อไปนี้ เวอร์ชันของวิธีการ PutAppointment ใช้ฟิลด์ในการนัดหมายที่ผู้ใช้สามารถแก้ไขได้ในแอป แทนที่จะเป็นวัตถุ การนัดหมาย แบบสมบูรณ์

    [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();
    }
    

    หมายเหตุ

    ตามกฎทั่วไป การดำเนินการ PUT ควรแก้ไขเฉพาะข้อมูลที่ผู้ใช้ควรได้รับอนุญาตให้อัปเดต ไม่จำเป็นต้องเป็นทุกฟิลด์ในเอนทิตี

  9. เปิดไฟล์ ScheduleEngineerController.cs และเพิ่มวิธีการ GetScheduleEngineerAppointments ต่อไปนี้ในคลาส 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.
    
    
  10. แก้ไขไฟล์ CustomerController.cs และเพิ่มวิธีการ GetAppointments และ GetNotes ดังที่แสดงให้เห็นในคลาส CustomerController

    [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();
        }
    
        ...
    }
    

    วิธีการ GetAppointments ค้นหาการนัดหมายทั้งหมดสำหรับลูกค้าที่ระบุ วิธีการ GetNotes ดึงบันทึกย่อทั้งหมดที่ช่างเทคนิคทำไว้ในการพบลูกค้าครั้งก่อน

  11. แก้ไขไฟล์ appSettings.json และเพิ่มสตริงการเชื่อมต่อสำหรับฐานข้อมูล KnowledgeDB สตริงนี้ควรเป็นสตริงเดียวกับที่คุณเคยเขียนถึงไฟล์ 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": "*"
    }
    
  12. ในหน้าต่าง เทอร์มินัล รวบรวมและสร้าง Web API

    dotnet build
    

    Web API ควรสร้างโดยไม่ต้องรายงานข้อผิดพลาดหรือคำเตือนใดๆ

  13. ในหน้าต่าง เทอร์มินัล ให้จัดแพคเกจ Web API ให้พร้อมสำหรับการปรับใช้กับ Azure

    dotnet publish -c Release -o ./publish
    
  14. ใน Visual Studio Code คลิกขวาที่โฟลเดอร์ เผยแพร่ แล้วเลือก ปรับใช้กับ Web App ปรับใช้กับเว็บแอป Azure เดียวกับที่คุณสร้างไว้ก่อนหน้านี้ อนุญาตให้วิซาร์ดเขียนทับเว็บแอปที่มีอยู่ด้วยรหัสใหม่

  15. เมื่อการปรับใช้งานเสร็จสิ้น ให้เรียกดูเว็บไซต์ แต่เปลี่ยน URL ในเบราว์เซอร์เป็น https://<webapp name>.azurewebsites.net/swagger ตรวจสอบว่าการดำเนินการสำหรับตัวควบคุม การนัดหมาย, ลูกค้า และ ScheduleEngineer ขณะนี้พร้อมใช้งานแล้ว

ขณะนี้ Web API พร้อมที่จะรวมเข้ากับแอปแล้ว