共用方式為


第 7 章:新增應用程式的功能

Kiana 和 Maria 非常高興地向現場技術人員 Caleb 展示了庫存管理應用程式。 Caleb 很滿意,但建議新增一些其他使用者介面功能,好讓應用程用起來更便利。 具體來說,Caleb 希望能夠:

  • 新增在鍋爐或空調裝置上完成的工作相片,並將其新增到編輯約會畫面的約會詳細資料中。 此影可像做為進行修復書面證據的證明。 編輯約會畫面目前可讓使用者將圖像新增至約會,但由於此功能未能徹底執行,因此該圖像未儲存。 造成此疏漏的原因是 Kiana 和 Preeti 需要確定儲存圖像資料的最佳位置。 Caleb 希望盡快新增此功能。

  • 查看客戶的完整約會歷史記錄,以追蹤所要求的修復並監視任何可能需要重複呼叫技術人員的現存問題。

  • 零件詳細資料畫面中訂購零件。

此外,零件詳細資料畫面上的圖像控制項會顯示儲存在指定 URL 上的圖像。 目前,資料中的 URL 只是預留位置。 就像約會畫面上的相片一樣,Kiana 和 Preeti 需要確定儲存圖像的最佳位置,以便應用程式使用它們。

將相片新增至約會

相片需要儲存在應用程式可存取的位置。 出於效能和安全性的原因,Preeti 不想將相片儲存在 OneDrive 或 Azure SQL 資料庫中。 相反地,他們決定使用 Azure Blob 儲存體。 Blob 儲存體為容納大型二進位物件而進行了最佳化,不只強固還具有內建安全性。 Power Apps 具有允許存取 Blob 儲存體的連接器。 Maria 建議新增拍照畫面,以改善 Caleb 的使用者體驗。

詳細資訊:Azure Blob 儲存體

Preeti 透過執行以下步驟從 Azure 入口網站建立 Blob 儲存體帳戶:

  1. Azure 入口網站首頁頁面中,選取 + 建立資源。 在搜尋服務商場方塊中,輸入儲存體帳戶,然後選取輸入

    Azure Marketplace 搜尋。

  2. 儲存體帳戶頁面上,選取建立

  3. 建立儲存體帳戶頁面上,輸入下列詳細資料,然後選取檢閱 + 建立

    • 訂閱︰選取您的訂閱
    • 資源群組:webapi_rg
    • 儲存體帳戶名稱:提供全域唯一的名稱,並將其記下以供日後使用
    • 位置:選取您最近的位置
    • 效能:標準
    • 帳戶類型:BlobStorage
    • 複寫:RA-GRS

    建立 Azure 儲存體帳戶。

  4. 在驗證頁面上,選取 建立,並等待儲存體帳戶佈建。

  5. 移至新儲存體帳戶的頁面。

  6. 概觀頁面上,選取容器

    儲存體帳戶概觀頁面。

  7. 容器頁面上,選取 + 容器。 建立名為相片的新容器,然後選取建立。 將公用存取等級變更為 Blob

    建立相片容器。

  8. 返回儲存體帳戶的概觀頁面,在 [設定] 下選取存取金鑰。 在存取金鑰頁面上,選取顯示金鑰。 記下 key1 的金鑰值。

    儲存體帳戶存取金鑰。

Preeti 會提供儲存體帳戶名稱和金鑰給 Kiana,後者使用此資訊透過以下步驟為應用程式建立自訂連接器:

  1. 登入 Power Apps

  2. 在左窗格中,展開資料並選取連線。 應列出該應用程式使用的現有連線。 選取 + 新增連線

    Power Apps 連線頁面。

  3. 新增連線頁面上,向下捲動,選取連線,選取Azure Blob 儲存體,然後選取建立

    選取 Azure Blob 儲存體連接器。

  4. Azure Blob 儲存體對話方塊中,輸入 Preeti 提供的儲存體帳戶名稱和存取金鑰,然後選取建立

    輸入儲存體認證。

  5. 等待新連線建立。 新連線應該會出現在連線清單中。

Maria 可以使用此連線到應用程式中的 Blob 儲存體來儲存和擷取相片圖像。 Maria 的首要工作是依照下列步驟將連線新增至應用程式:

  1. 開啟 VanArsdelApp 應用程式,以在 Power Apps Studio 中進行編輯。

  2. 資料窗格中,選取新增資料,搜尋 Azure Blob 儲存體連接器,然後選取連接器。

    搜尋 Blob 儲存體連接器。

  3. Azure Blob 儲存體對話方塊中,選取 Azure Blob 儲存體連接器,以將其新增至您的應用程式。

    新增 Blob 儲存體連線。

Maria 的下一個工作是新增畫面,讓技術人員或工程師儲存相片。 Maria 決定使用 [圖片] 控制項新增畫面。 當應用程式在行動裝置上執行時,此控制項可與相機整合以讓技術人員拍照。 在其他裝置上,此控制項會提示使用者上載圖像檔案。 Maria 依照下列步驟從 EditAppointment 畫面新增這個新畫面的連結:

  1. 插入功能表中,選取新畫面,然後選取可捲動範本。

    可捲動範本中的新畫面。

  2. 樹狀檢視窗格中,選取新畫面,然後將它重新命名為 TakePhoto

  3. 將此畫面上LblAppNameX控制項的文件屬性變更為拍照

  4. 從畫面上刪除畫布X 控制項。

  5. 插入功能表的媒體下拉式清單中,選取新增圖片來建立新的圖片控制項。

    新增圖片控制項。

    注意

    圖片控制項實際上是一個複合自訂元件,可讓使用者將圖片新增至畫面並顯示結果。

  6. 調整圖片控制項的大小並重新置放,以佔用畫面的主體。

  7. 樹狀檢視窗格中,選取 AppointmentDetails 畫面上的 IconBackarrow X 控制項,然後選取複製

    複製 [上一步箭頭] 控制項。

  8. 樹狀檢視功能表上,以滑鼠右鍵按一下 TakePhoto 畫面,然後選取貼上IconBackArrowX 控制項就會新增至畫面。

    在 TakePhoto 畫面中貼上 [上一步箭頭] 控制項。

  9. IconBackArrowX 控制項移至標題列的左上角。

  10. 樹狀檢視窗格中,選取 TakePhoto畫面上的 IconBackarrow X 控制項。 在右窗格的進階索引標籤上,將 OnSelect 動作屬性改為 Navigate(EditAppointment, ScreenTransition.None)

  11. 將新的儲存圖示控制項新增至標題列的右上角。 將此控制項的 Visible 屬性設為 If(IsBlank(AddMediaButton1.Media), false, true)

    如果使用者未選取圖像,此設定將隱藏儲存圖示。

    新增儲存圖示控制項。

  12. 儲存圖示控制項 OnSelect 動作屬性中的公式變更為以下內容。

    Set(ImageID, GUID() & ".jpg");
    
    AzureBlobStorage.CreateFile("photos", ImageID, AddMediaButton1.Media);
    
    Patch(appointmentsCollection, LookUp(appointmentsCollection,id=BrowseAppointmentsGallery.Selected.id), {imageUrl:"https://myappphotos.blob.core.windows.net/photos/" & ImageID});
    
    Navigate(EditAppointment,ScreenTransition.Cover);
    

    將**<storage account name>** 取代為 Preeti 建立的 Azure 儲存體帳戶名稱。

    此程式碼會將圖像上傳至 Blob 儲存體中的照片容器。 會為每個圖像指定唯一的檔案名稱。 修補程式功能會使用 Blob 儲存體中的圖像 URL 更新約會記錄中的 imageUrl 屬性。

  13. 樹狀檢視窗格中,展開 AddMediaWithImageX 控制項。 修改 UploadedImageX控制項的 Image 屬性,並將其設為 AppointmentImage

    AppointmentImage 是一個變數,會填入使用者上傳的圖像,或是做為拍照的結果。 您稍後會在 EditAppointment 畫面中初始化此變數。

  14. 樹狀檢視窗格中,選取 AddMediaButtonX 控制項。 將此控制項的 UseMobileCamera 屬性設為 True。 將該控制項的 OnChange 動作屬性設為以下內容。

    Set(AppointmentImage, AddMediaButton1.Media)
    

    此公式會變更 AppointmentImage 變數以參照新圖像。 UploadedImageX 控制項將會顯示此圖像。

  15. 樹狀檢視窗格中,選取 EditAppointment 畫面。

  16. 展開 EditFormX 控制項。 在 Image_DataCardX 控制項下移除 AddPictureX 控制項。

    移除 AddPicture 控制項。

  17. 選取 ImageX 控制項。 變更下列屬性:

    • 圖像:Parent.Default
    • X:30
    • Y:DataCardKeyX.Y + DataCardKeyX。高度 + 150 (其中 DataCardKeyX 是包含 ImageX 控制項的資料卡片)
    • 寬度:Parent.Width - 60
    • 高度:400

    注意

    圖像控制項將下移至畫面底部下方,但會自動新增捲軸以便顯示圖像。

  18. 相機圖示新增至資料卡片,然後將其置於圖像標籤與 ImageX 控制項之間。 將控制項的名稱變更為CameraIcon

    注意

    請確定您已選取相機圖示控制項,而不是相機媒體控制項

    新增 [相機] 圖示。

  19. CameraIcon 控制項的 OnSelect 動作屬性設為以下內容。

    Set(AppointmentImage, SampleImage);
    
    Navigate(TakePhoto, ScreenTransition.None);
    

    當使用者選取此圖示時,他們將移至 TakePhoto 畫面,他們可以在那裡拍照或上傳圖像。 顯示的初始圖像將會是預設的範例圖像。

若要測試應用程式,請執行以下動作:

  1. 樹狀檢視窗格中,選取首頁畫面。

  2. 選取 F5 以預覽應用程式。

  3. 首頁畫面上,選取約會

  4. 在瀏覽畫面中,選取任一約會。

  5. 在約會的 [詳細資料] 畫面中,選取畫面標題中的 [編輯] 圖示。

  6. 在編輯畫面上,選取圖像的相機圖示。

  7. 確認出現拍照畫面。

  8. 選取變更圖片並上傳您選擇的圖片 (或如果您正在行動裝置上執行應用程式,則可以拍照)。

  9. 選取儲存。 確認圖像出現在詳細資料頁面上,然後選取勾號圖示將變更存回資料庫。

  10. 關閉預覽視窗並返回 Power Apps Studio。

顯示零件的圖像

在確定 Blob 儲存體是儲存約會相關圖片的最佳位置後,Preeti 和 Kiana 決定使用相同的方法來儲存零件的圖像。 這種方法的主要優點是不需要對應用程式進行任何修改。 應用程式會重複使用相同的儲存體帳戶和相同的連線。 做為獨立的移轉練習,他們可以執行以下作業:

  1. 建立新的 Blob 儲存體容器。

  2. 將零件圖像上傳至此容器。

  3. InventoryDB 資料庫零件表格中的 ImageUrl 參照變更為每個圖像的 URL。

應用程式會自動挑選每個零件圖像的新 URL,而 PartDetails 畫面上的圖像控制項將會顯示圖像。

追蹤客戶的約會歷史記錄

Maria 想能透過建立自訂元件,快速查看客戶先前技術人員造訪的所有歷史記錄新增到應用程式中。 Maria 與 Caleb 合作,根據他們想看到的資訊規劃出簡單的設計,其中包括附註和每次造訪的日期。

客戶約會歷史記錄的資料。

透過查看資料,Maria 認為資源庫控制項是在畫面上顯示表格資料的最佳方法。

Maria 建立自訂元件,如下所示:

  1. 使用 Power Apps Studio,在樹狀檢視窗格中選取元件,然後選取 + 新元件

    建立新元件。

    建立一個名為 Component1 的新空白元件。 將元件重新命名為 DateHistoryComponent

    重新命名元件。

  2. 插入功能表中選取資源庫,然後選擇空白彈性高度資源庫範本。

    新增資源庫控制項。

  3. 移動資源庫控制項,並調整它的大小以填入自訂元件。

  4. 選取插入窗格中的新增項目,然後選取文字標籤

    將文字標籤新增至元件。

  5. 樹狀檢視窗格中,將標籤控制項重新命名為 NotesLabel。 將 Overflow 屬性設為 Overflow.Scroll。 此設定可讓控制項顯示多行文字,並允許使用者捲動瀏覽。 設定下列屬性,讓您可以定位控制項並調整大小:

    • LineHeight:2
    • X:28
    • Y:18
    • 寬度:574
    • 高度:140
  6. 將第二文字標籤新增至控制項。 將此控制項重新命名為 DateLabel,並設定下列屬性:

    • LineHeight:2
    • X:28
    • Y:174
    • 寬度:574
    • 高度:70
  7. 若要查看控制項在插入應用程式後及其主題顯示的外觀,請在樹狀檢視窗格上,選取 DateHistoryComponent。 在右窗格的進階索引標籤上,選取填入欄位,並將色彩變更為 RGBA(0, 0, 0, 1)

    檢視元件。

  8. 插入窗格中,展開形狀,然後將矩形控制項新增至自訂元件。 設定控制項的下列屬性:

    • X:0
    • Y:273
    • 寬度:Parent.Width
    • 高度:2

    此控制項會當做顯示在資源庫中的記錄間分隔符號。

    新增矩形控制項。

Maria 熟悉將控制項新增至畫面,以及使用 Power Apps 零件應用程式的過程。 但是,可重複使用元件的運作方式並不完全相同。 Kiana 向 Maria 說明,為了能在自訂元件中使用資料,必須新增其他自訂輸入屬性。 Kiana 還解釋,Maria 需要提供這些屬性的範例資料,以便在元件中參考控制項中的資料欄位,如下所示:

  1. 樹狀檢視窗格中,選取 DateHistoryComponent。 在右側窗格的屬性索引標籤,選取新自訂屬性

    新增自訂屬性。

  2. 新增自訂屬性對話方塊中,指定下列值,然後選取建立

    • 顯示名稱:資料
    • 名稱:資料
    • 描述:客戶的約會表格,顯示附註及日期
    • 屬性類型:輸入
    • 資料類型:表格
    • 當值變更時提高 OnReset:保留空白

    新增自訂屬性屬性。

  3. 若要變更控制項顯示的範例資料,請選取新的資料自訂屬性。 在公式欄位中,輸入表格 ({附註:「範例附註欄位文字。」,'約會日期':Text(Today())})

    變更範例資料。

  4. 樹狀檢視窗格中,選取 DateHistoryComponent 中的 GalleryX 控制項,並將其重新命名為 AppointmentHistory

  5. 在右窗格的進階索引標籤上,將 AppointmentHistory 資源庫控制項的 Items 屬性設為 Parents.Data

    更新資源庫控制項的 Items 屬性。

  6. 選取 NotesLabel 控制項。 在進階索引標籤的右窗格上,將 Text 屬性變更為 ThisItem.Notes,並將 Size 屬性變更為 20

    注意

    Size 屬性指定控制項所顯示的文字字型大小。

  7. 選取 DateLabel 控制像將 Text 屬性變更為 ThisItem.'Appointment Date',並將 Size 屬性變更為 20。 自訂元件中的欄位應顯示範例資料。

    包含範例資料的自訂元件。

自訂元件已完成。 Maria 使用此元件建立新畫面,來顯示客戶的約會歷史記錄,如下所示:

  1. 樹狀檢視窗格中,選取畫面索引標籤。

  2. 展開 BrowseAppointments 畫面,展開 BrowseAppointmentsGallery 控制項,然後選取 Body1_1 控制項。 在插入功能表上,選取圖示,然後選取詳細資料清單圖示。

    新增詳細資料清單圖示。

  3. 將圖示控制項的名稱變更為 ViewAppointments

  4. 樹狀檢視功能表中,選取 BrowseAppointmentsGallery 控制項。 在右側窗格的進階索引標籤,將 TemplateSize 屬性變更為 220。 增加此屬性會擴充資源庫中的可用空間。

  5. ViewAppointments 圖示移至客戶名稱下方的空白空間。

    已修改的約會資料庫。

  6. 選取 ViewAppointments 圖示控制項。 將 OnSelect 動作屬性設定為下列公式。

    ClearCollect(customerAppointmentsCollection, FieldEngineerAPI.getapicustomeridappointments(ThisItem.customerId));
    
    Navigate(AppointmentsHistoryScreen, ScreenTransition.Fade)
    

    此公式使用所選客戶的約會填入名為 customerAppointmentsCollection 的集合,然後移至 AppointmentHistoryScreen 顯示這些約會。 您將會在下列步驟中建立此畫面。

  7. 插入功能表中,選取新畫面,然後選取可捲動範本。

    可捲動範本的新畫面。

  8. 將新畫面的名稱變更為 AppointmentHistoryScreen

  9. 刪除新增至此畫面的 CanvasX 控制項。

    刪除畫布控制項。

  10. 選取此畫面上的 LblAppNameX 控制項。 在右窗格的進階索引標籤上,將 Text 屬性變更為以下內容。

    "Appointments History for " &  BrowseAppointmentsGallery.Selected.customer.name
    
  11. LblAppNameX 控制項設定以下屬性,以調整位置和大小:

    • X:90
    • Y:0
    • 寬度:550
    • 高度:140
  12. 選取 RectQuickActionBarX 控制項,並將 Height 屬性設為 140

  13. 在標題左側的畫面標題中新增左圖示控制項。 將此控制項的 OnSelect 動作屬性設為 Navigate(BrowseAppointments, Transition.None)

    空白 AppointmentsHistory 畫面。

  14. 插入功能表上,選取自訂,然後選取 DateHistoryComponent

    新增 DateHistory 元件。

  15. 移動並調整元件的大小,使其佔用標題下方的畫面主體。

    調整元件大小。

  16. 設定此元件的下列屬性:

    • 資料:customerAppointmentsCollection
    • 約會日期:startDateTime
    • 附註:notes
  17. 儲存應用程式。

若要測試應用程式,請執行以下動作:

  1. 樹狀檢視窗格中,選取首頁畫面。

  2. 選取 F5 以預覽應用程式。

  3. 首頁畫面上,選取約會

  4. 在瀏覽畫面中,為任何約會選取詳細資料清單圖示。

  5. 驗證是否出現所選客戶的約會歷史紀錄畫面。

  6. 關閉預覽視窗並返回 Power Apps Studio。

訂購零件

該系統的主要要求是可讓技術人員在造訪客戶時訂購所需的任何零件。 如果零件有庫存,則可以安排再次拜訪,以在下一個方便的日期為客戶完成維修。 如果零件目前無存貨且必須訂購,則技術人員可以告知客戶。 然後,當 Maria 收到零件抵達倉庫的通知後,Malik 就可以安排與客戶的約會。

該應用程式的預訂零件使用 InventoryDB 資料庫中的表格,如下圖所示。 訂單表格包含有關零件訂單的資訊。 預訂表格會列出技術人員和工程師對零件的預訂要求。 工程師表格會提供要預訂的工程師姓名和連絡電話,讓庫存經理 Maria 能在需要時輕鬆查詢。

預訂資料模型。

為了支援此功能,Kiana 必須使用下列方法更新 Web API,此方法會擷取指定零件的預訂項目數目,如下所示:

  1. 在 Visual Studio Code 中開啟 FieldEngineerApi Web API 專案。

  2. 將名為 Order.cs 的檔案新增至模型資料夾。 將下列代碼新增至此檔案。 訂單類別會追蹤零件訂單的詳細資料。

    using System;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace FieldEngineerApi.Models
    {
        public class Order 
        {
            [Key]
            public long Id { get; set; }
    
            public long BoilerPartId { get; set; }
    
            public BoilerPart BoilerPart { get; set; }
    
            public long Quantity { get; set; }
    
            [Column(TypeName = "money")]
            public decimal TotalPrice { get; set; }
    
            [Display(Name = "OrderedDate")]
            [DataType(DataType.DateTime)]
            [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
            public DateTime OrderedDateTime { get; set; }
    
            public bool Delivered { get; set; }
    
            [Display(Name = "DeliveredDate")]
            [DataType(DataType.DateTime)]
            [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
            public DateTime? DeliveredDateTime { get; set; }
        }
    }
    
  3. 將另一個名為 Reservation.cs 的新檔案新增到模型資料夾中,並將以下代碼新增到此檔案中。 預訂類別包含指定零件目前為其他客戶預訂的項目數目資訊。

    using System;
    using System.ComponentModel.DataAnnotations;
    
    namespace FieldEngineerApi.Models
    {
        public class Reservation
        {
            [Key]
            public long Id { get; set; }
    
            public long BoilerPartId { get; set; }
    
            public BoilerPart BoilerPart { get; set; }
    
            public int NumberToReserve { get; set; }
    
            public string EngineerId { get; set; }
    
            public InventoryEngineer Engineer { get; set; }
        }
    }
    
  4. 使用以下代碼將名為 InventoryEngineer.cs, 的檔案新增至模型資料夾。 InventoryEngineer 類別會記錄哪些工程師預訂了什麼項目。

    using System.ComponentModel.DataAnnotations;
    using System.Collections.Generic;
    
    namespace FieldEngineerApi.Models
    {
        public class InventoryEngineer
        {
            [Key]
            public string Id { get; set; }
    
            [Required]
            public string Name { get; set; }
    
            public string ContactNumber { get; set; }
    
            public List<Reservation> Reservations { get; set; }
        }
    }
    
  5. 模型資料夾中開啟 InventoryContext.cs 檔案,然後將下列陳述式新增至 InventoryCoNtext 類別。

    public class InventoryContext : DbContext
    {
        public InventoryContext(DbContextOptions\<InventoryContext\> options)
            : base(options)
        {
    
        }
    
        public DbSet<BoilerPart> BoilerParts { get; set; }
        public DbSet<InventoryEngineer> Engineers { get; set; }
        public DbSet<Order> Orders { get; set; }
        public DbSet<Reservation> Reservations { get; set; }
    }
    
  6. 在 Visual Studio Code 的終端機視窗中,執行下列命令來建立處理訂單和預訂的控制器。

    dotnet aspnet-codegenerator controller ^
        -name OrdersController -async -api ^
        -m Order ^
        -dc InventoryContext -outDir Controllers
    
    dotnet aspnet-codegenerator controller ^
        -name ReservationsController -async -api ^
        -m Reservation ^
        -dc InventoryContext -outDir Controllers
    
  7. 控制器資料夾中開啟 BoilerPartController.cs 檔案,然後將以下 GetTotalReservations 方法新增至 BoilerPartsController 類別。

    public class BoilerPartsController : ControllerBase
    {
        private readonly InventoryContext _context;
    
        public BoilerPartsController(InventoryContext context)
        {
            _context = context;
        }
    
        ...
    
        // GET: api/BoilerParts/5/Reserved 
        [HttpGet("{id}/Reserved")]
        public async Task<ActionResult<object>> GetTotalReservations(long id)
        { 
            var reservations = await _context
                .Reservations
                .Where(r => r.BoilerPartId == id) 
                .ToListAsync();
    
            int totalReservations = 0; 
    
            foreach(Reservation reservation in reservations) 
            { 
                totalReservations += reservation.NumberToReserve; 
            } 
    
            return new {id, totalReservations}; 
        }
        ...
    }
    
  8. 編輯 OrdersController.cs 檔案,並修改 OrdersController 類別中的 PostOrder 方法,如下所示。

    [HttpPost]
    public async Task<ActionResult<Order>> PostOrder(long boilerPartId, int quantity)
    {
        var part = await _context.BoilerParts.FindAsync(boilerPartId);
    
        Order order = new Order 
        {
            BoilerPartId = boilerPartId,
            Quantity = quantity,
            OrderedDateTime = DateTime.Now,
            TotalPrice = quantity * part.Price
        };
    
        _context.Orders.Add(order);
        await _context.SaveChangesAsync();
    
        return CreatedAtAction("GetOrder", new { id = order.Id }, order);
    }
    
  9. 編輯 ReservationsController.cs 檔案。 修改 ReservationsController 類別中的 PostReservation 方法,如下所示。

    [HttpPost]
    public async Task<ActionResult<Reservation>> PostReservation(long boilerPartId, string engineerId, int quantityToReserve)
    {
        Reservation reservation = new Reservation 
        {
            BoilerPartId = boilerPartId,
            EngineerId = engineerId,
            NumberToReserve = quantityToReserve
        };
    
        _context.Reservations.Add(reservation);
        await _context.SaveChangesAsync();
    
        return CreatedAtAction("GetReservation", new { id = reservation.Id }, reservation);
    }
    
  10. 在終端機視窗中,執行以下命令來組建和發佈準備部署的 Web API。

    dotnet build
    dotnet publish -c Release -o ./publish
    
  11. 在 Visual Studio Code 中,右鍵點擊發佈資料夾,然後選取部署至 Web 應用程式

Preeti 現在可以更新 VanArsdel 應用程式所使用的 API 管理服務,以反映更新的 Web API。 這會不間斷地進行變更; 現有的作業將繼續運作,不同之處在於新的控制器和用於預訂和下單的作業。 Preeti 執行以下工作:

注意

Preeti 可以選擇刪除現有的 Field Engineer API,並以新版本取代它,但是這種方式會破壞目前可能正在使用 API 的任何現有應用程式。 最好保留現有的 API,並將修改部分新增為修訂版。

  1. 在 Azure 入口網站中,移至 API 管理服務。

  2. API 管理服務頁面中,在 API 下地左窗格選取 API

  3. 選取 Field Engineer API,選取省略符號功能表,然後選取新增修訂

    將修訂新增至 Field Engineer API。

  4. 建立 Field Engineer API 新修訂對話方塊中,輸入描述為零件預訂和訂單新增 GET 作業和 POST 作業,然後選取建立

    建立修訂。

  5. 修訂 2 頁面中,選取設計

    設計修訂。

  6. 設計頁面上,選取新增作業。 在前端窗格上,設定下列屬性,然後選取儲存。 此作業可用於擷取預訂指定鍋爐零件的項目數目:

    • 顯示名稱:api/BoilerParts/{id}/Reserved
    • 名稱:api-boilerparts-id-reserved
    • URL: GET api/BoilerParts/{id}/Reserved

    新增預訂的 API 作業。

  7. 在新作業的測試索引標籤上,將識別碼參數設為有效零件編號 (圖像中的範例會使用零件 1),然後選取傳送

    測試 Web API。

  8. 驗證測試是否成功。 該作業應以 HTTP 200 回覆完成,且主體會顯示該產品的預訂數目。

    測試回覆。

  9. 設計頁面上,選取新增作業。 在前端窗格上,設定下列屬性 (此作業定義用於建立新訂單的 POST 要求):

    • 顯示名稱:api/Orders - POST
    • 名稱:api-orders-post
    • URL:POST api/Orders
  10. 查詢索引標籤上,選取 + 新增參數,新增以下參數,然後選取儲存

    • 名稱:boilerPartId,描述:鍋爐零件識別碼,類型:
    • 名稱:數量,描述:數量,類型:整數

    將參數新增至 API 管理查詢作業。

  11. 前端窗格上選取新增作業,設定下列屬性 (此作業定義用於建立新預訂的 POST 要求):

    • 顯示名稱:api/Reservations - POST
    • 名稱:api-reservations-post
    • URL:POST api/Reservations
  12. 查詢索引標籤上,新增以下參數,然後選取儲存

    • 名稱:boilerPartId,描述:鍋爐零件識別碼,類型:
    • 名稱:engineerId,描述:工程師識別碼,類型:字串
    • 名稱:quantityToReserve,描述:要預訂的數量,類型:整數
  13. 修訂索引標籤上,選取新版本。 在此版本的省略符號功能表中,選取設為最新

    設定修訂的最新版本。

  14. 使修訂保持最新對話方塊中,選取儲存

  15. 在網頁瀏覽器中開啟其他頁面,然後移至 URL https://<APIM name>.azure-api.net/api/boilerparts/1/reserved,其中 <APIM name> 是您的 API 服務名稱。 確認是否收到與以下類似的回復。

    {"id":1,"totalReservations":5}
    

更新的 Web API 現在可以使用。 在理論上,Kiana 可以為更新的 Web API 建立新的自訂連接器,並將它新增至應用程式中。 然後,應用程式可以執行自己的邏輯,以確定指定產品目前有多少庫存,有多少已預訂,並將結果與所需的項目數量進行比較,在必要時下單以增加庫存,或從現有庫存預訂項目。 但是,在 Azure 邏輯應用程式中可以更好地執行這種邏輯。 當技術人員想要預訂或訂購某個零件時,Power Apps 可以透過自訂連接器來呼叫邏輯應用程式。

若要建立邏輯應用程式,Kiana 可以使用下列步驟:

注意

為簡單起見,在此範例中建立的邏輯應用程式是非交易式的。 在檢查零件的可用性與進行預訂之間,並行使用者可能會進行衝突的預訂。 您可以透過使用 InventoryDB 資料庫中儲存的程序取代此邏輯應用程式中的某些邏輯,來實現交易式語義。

  1. Azure 入口網站首頁頁面中,選取 + 建立資源

  2. 搜尋服務商場方塊中,輸入邏輯應用程式,然後選取輸入

  3. 邏輯應用程式頁面上,選取建立

    建立邏輯應用程式。

  4. 建立邏輯應用程式頁面上,輸入下列值,然後選取檢閱 + 建立

    • 訂閱︰選取您的 Azure 訂閱
    • 資源群組:webapi_rg
    • 邏輯應用程式名稱:FieldEngineerPartsOrdering
    • 地區:選取您用於 Web API 的相同位置。
    • 與整合服務環境的關聯:保留空白
    • 啟用記錄分析:保留空白
  5. 在驗證頁面上,選取建立,然後等待部署邏輯應用程式。

  6. 部署完成後,請選取前往資源

  7. 邏輯應用程式設計師頁面上,向下捲動至 範本 區段,然後選取 空白邏輯應用程式

    選取空白邏輯應用程式範本。

  8. 在 全部 索引標籤的 搜尋連接器和觸發程序 文字方塊中,選取要求

    選取要求觸發程序。 

  9. 觸發程序索引標籤上,選取收到 HTTP 要求時

    收到 HTTP 要求時觸發。

  10. 要求主體 JSON 結構描述方塊中,輸入下列結構描述,然後選取 + 新步驟

    {
        "type": "object",
        "properties": {
            "boilerPartId": {
                "type": "integer"
            },
            "numberToReserve": {
                "type": "integer"
            },
            "engineerId": {
                "type": "string"
            }
        }
    }
    

    邏輯應用程式要求結構描述。

    此結構描述定義了邏輯應用程式預期的 HTTP 要求內容。 要求主體包含鍋爐零件的識別碼、要預訂的項目數目,以及提出要求的工程師識別碼。 當工程師想要預訂零件時,應用程式會傳送此要求。

  11. 選擇作業方塊中,選取全部,然後選取 HTTP

    SelectH tthe HTTP 作業選項。

    邏輯應用程式會呼叫 BoilerParts{id} 作業,以從該應用程式的要求中擷取有關鍋爐零件的資訊。

  12. 動作窗格中,選取 HTTP 動作。

    選取 HTTP 動作選項。

  13. HTTP 動作方塊的省略符號功能表中,選取重新命名,然後將動作名稱變更為 CheckBoilerPart

    重新命名 HTTP 動作。

  14. 設定 HTTP 動作的屬性,如下所示,然後選取 + 新步驟

    • 方法:GET
    • URI: https://<APIM name>.azure-api.net/api/boilerparts/,其中 <APIM name> 是您的 API 管理服務的名稱。 在此 URI 的動態內容方塊中,於動態內容索引標籤選取 boilerPartId

    為 HTTP 動作指定動態內容。

  15. 選擇作業方塊的搜尋連接器和動作方塊中,輸入剖析 JSON,然後選取剖析 JSON 動作。

    選取剖析 JSON 動作。

  16. 使用剖析 JSON 動作的省略符號功能表,將動作重新命名為 ParseBoilerPart

  17. ParseBoilerPart 動作的內容方塊中,選取動態內容方塊中的主體。 在結構描述方塊中,輸入以下 JSON 結構描述,然後選取 + 新步驟

    {
        "type": "object",
        "properties": {
            "id": {
                "type": "integer"
            },
            "name": {
                "type": "string"
            },
            "categoryId": {
                "type": "string"
            },
            "price": {
                "type": "number"
            },
            "overview": {
                "type": "string"
            },
            "numberInStock": {
                "type": "integer"
            },
            "imageUrl": {
                "type": "string"
            },
        }
    }
    

    剖析 BoilerPart 物件。

    此動作會剖析 getBoilerParts/{id} 要求傳回的回覆訊息。 回覆包含鍋爐零件的詳細資料,包括目前庫存的數目。

  18. 在新步驟的選擇作業方塊中,選取 HTTP 連接器。

  19. 動作索引標籤中,選取 HTTP 動作。

  20. 使用作業的省略符號功能表,將作業重新命名為 CheckReservations

  21. 設定此作業的以下屬性,然後選取 + 新步驟

    • 方法:GET
    • URI:https://<APIM name>.azure-api.net/api/boilerparts/。 與之前一樣,在此 URI 的動態內容方塊中,於動態內容索引標籤選取 boilerPartId。 在 URI 欄位中,將文字 /reserved 附加在 boilerPartId 預留位置後面。

    CheckReservations 步驟。

  22. 在新動作選擇作業方塊的搜尋連接器和動作方塊中,輸入剖析 JSON,然後選取剖析 JSON 動作。

  23. 將作業重新命名為 ParseReservations

  24. Content 屬性設為主體

  25. 輸入下列結構描述,然後選取 + 新步驟

    {
        "type": "object",
        "properties": {
            "id": {
                    "type": "integer"
            },
            "totalReservations": {
                    "type": "integer"
            }
        }
    }
    

    剖析預訂資料。

  26. 在新動作選擇作業方塊的搜尋連接器和動作方塊中,輸入條件,然後選取條件控制項動作。

    選取條件控制項。

  27. 將作業重新命名為 CompareStock

  28. 選取選擇值方塊。 在新增動態內容方塊的運算式索引標籤中,輸入下列運算式,然後選取確定

    add(body('ParseReservations')?['totalReservations'], triggerBody()?['numberToReserve'])
    

    此運算式會加總目前預訂之指定鍋爐零件的項目數目與工程師要求的數目。

    CompareStock 條件。

  29. 在條件下拉式清單方塊中,選取大於

  30. 在其餘的選擇值方塊動態內容方塊中,於動態內容索引標籤的 ParseBoilerPart 下,選取 numberInStock

    將總預訂與庫存中的項目數目進行比較。

  31. 如果需要的項目數目加上預訂的數目大於庫存量,則應用程式必須下單以補充庫存。 在 CompareStock 動作的 True 分支中,選取新增動作

  32. 在新作業的全部索引標籤上,選取 HTTP ,然後選取 HTTP 動作。

  33. 將作業重新命名為 PostOrder

  34. 設定下列 PostOrder 作業的屬性:

    • 方法:POST
    • URI:https://<APIM name>.azure-api.net/api/orders
    • 查詢表格的第一資料列中,輸入金鑰 boilerPartId。 若要新增動態內容方塊中的值,請在動態內容索引標籤上,選取 boilerPartId
    • 查詢表格的第二資料列中,輸入金鑰 quantity。 在值欄位中,輸入 50

    張貼要求以訂購更多零件。

    當庫存不足時,邏輯應用程式會自動訂購 50 個指定零件項目。

    注意

    邏輯應用程式假設工程師不會在單一要求中嘗試預訂超過 50 個指定零件項目!

  35. CompareStock 動作的 False 分支保留空白。

  36. CompareStock 動作下方選取 + 新步驟

  37. 在新作業的全部索引標籤上,選取 HTTP ,然後選取 HTTP 動作。

  38. 將作業重新命名為 PostReservation

  39. 設定下列 PostReservation 作業的屬性:

    • 方法:POST
    • URI:https://<APIM name>.azure-api.net/api/reservations
    • 查詢表格的第一資料列中,輸入金鑰 boilerPartId。 在動態內容索引標籤中針對新增動態內容方塊中的值,選取 boilerPartId
    • 在第二資料列中,輸入金鑰 engineerId。 在動態內容索引標籤中針對新增動態內容方塊中的值,選取 engineerId
    • 在第三資料列中,輸入金鑰 quantityToReserve。 在動態內容索引標籤中針對新增動態內容方塊中的值,選取 numberToReserve
  40. 選取 + 新增步驟。 在選擇作業方塊中,搜尋並選取回覆動作。

  41. 設定以下回覆動作的屬性:

    • 狀態碼:200
    • 標題:金鑰 - 內容類型,值- 應用程式/json
    • 主體:在動態內容方塊中,從 PostReservation 要求選取 Body 元素。 這是在進行預訂時所傳回的主體。

    邏輯應用程式傳送的回覆訊息。

  42. 邏輯應用程式設計師頁面的左上角,選取儲存。 確認邏輯應用程式可以儲存,而不會發生任何錯誤。

若要建立 Power Apps 可用於觸發邏輯應用程式的自訂連接器,Kiana 在 Azure 入口網站中仍要執行下列步驟:

  1. 在邏輯應用程式的概觀頁面上,選取匯出

    匯出邏輯應用程式。

  2. 匯出至 Power Apps 窗格中,命名連接器 PartsOrderingConnector,選取您的 Power Apps 環境,然後選取確定

    匯出邏輯應用程式至 Power Apps。

  3. 登入 Power Apps

  4. 在您的環境中,在資料下選取自訂連接器,並確認已列出 PartsOrderingConnector

    Power Apps 自訂連接器。

Maria 現在可以修改 VanArsdel 應用程式,讓技術人員在拜訪客戶時訂購零件。 Maria 將訂單按鈕新增至 PartDetails 畫面,如下所示:

  1. 登入 Power Apps (如果尚未登入)。

  2. 應用程式下,選取 VanArsdelApp 應用程式。 在應用程式的省略符號功能表中,選取編輯

  3. 資料窗格中,選取新增資料,搜尋 PartsOrderingConnector 連接器,然後使用該連接器新增一個新的連線。

    將 PartsOrdering 連接器新增至應用程式。

  4. 樹狀檢視窗格中,展開 PartDetails 畫面,然後展開 DetailForm1 表單。

  5. 在右側屬性窗格中,選取編輯欄位。 在欄位窗格的省略符號功能表中,選取新增自訂卡片

    將自訂資料卡片控制項新增至應用程式。

  6. 樹狀檢視窗格中,將新卡片從 DataCard1 重新命名為 ReserveCard。 在設計檢視視窗中,調整卡片的大小,讓其佔用畫面的下半部,位於 Image_DataCard1 控制項下方。

    重新命名和調整資料卡片控制項的大小。

  7. 插入功能表的輸入子功能表中,將文字輸入控制項、按鈕控制項及標籤控制項新增至 ReserveCard 控制項。

  8. 調整控制項的大小和位置,讓它們相鄰,按鈕控制項在文字輸入控制項的右側,標籤按鈕控制項下方。

  9. 文字輸入控制項的屬性窗格上,清除預設屬性。

  10. 按鈕控制項的屬性窗格上,將Text 屬性設為 Reserve

    ParttDetails 畫面的版面配置。

  11. 文字輸入控制項重新命名為 NumberToReserve,將按鈕控制項重新命名為預訂,並將標籤控制項重新命名為訊息

  12. 訊息控制項的屬性窗格上,將 Text 屬性設為 Parts Reserved,並將 Visible 屬性設為 MessageIsVisible

    注意

    MessageIsVisible 是變數,您將在顯示畫面時將其初始化為 false,但如果使用者選取預訂按鈕,其會變更為 true

  13. 預訂按鈕控制項的 OnSelect 屬性設為以下公式。

    FieldEngineerPartsOrdering.manualinvoke({boilerPartId:ThisItem.id, engineerId:"ab9f4790-05f2-4cc3-9f01-8dfa7d848179", numberToReserve:NumberToReserve.Text});
    
    Set(MessageIsVisible, true);
    

    注意

    此公式使用硬式編碼工程師識別碼,來代表目前執行應用程式的技術人員。 第 8 章說明如何擷取已登入使用者的識別碼。

    此外,應用程式不會執行錯誤檢查;其假設預訂零件的要求一率成功。 如需錯誤處理的詳細資訊,請移至中的 Power Apps 中的錯誤功能

  14. PartDetails 畫面的 OnVisible 屬性設為 Set(MessageIsVisible, false)

若要測試應用程式,請執行以下動作:

  1. 樹狀檢視窗格中,選取首頁畫面。

  2. 選取 F5 以預覽應用程式。

  3. 首頁畫面上,選取零件

  4. 在瀏覽畫面中,選取任一零件。

  5. 零件詳細資料畫面上,向下捲動至預訂區段,輸入一個正整數值,然後選取預訂。 確認出現預訂零件訊息。

    已啟用具有預訂功能的 PartDetails 畫面。

  6. 關閉預覽視窗並返回 Power Apps Studio。

  7. 在 Azure 入口網站中,移至 InventoryDB SQL 資料庫頁面。

  8. 選取查詢編輯器,並使用密碼以 sqladmin 身分登入。

  9. 查詢 1窗格中,輸入下列查詢,然後選取執行。 確認您在 VanArsdel 應用程式進行的預訂有出現。

    SELECT * FROM [dbo].[Reservations]
    

    查詢結果在 SQL 資料庫中。