Lưu ý
Cần có ủy quyền mới truy nhập được vào trang này. Bạn có thể thử đăng nhập hoặc thay đổi thư mục.
Cần có ủy quyền mới truy nhập được vào trang này. Bạn có thể thử thay đổi thư mục.
Sau khi thiết lập rằng dữ liệu cho ứng dụng của kỹ thuật viên phải được lấy từ các hệ thống hiện có thông qua API Web, Maria và Kiana làm việc cùng nhau để xác định chính xác thông tin nào là cần thiết và ở định dạng nào. Sau đó, Kiana sẽ tạo một ứng dụng web hiển thị API Web thích hợp và sắp xếp để ứng dụng đó được lưu trữ trong Azure. Ứng dụng có thể kết nối với Azure từ bất kỳ nơi nào có kết nối không dây.
Xác định các hoạt động API Web: Quản lý hàng tồn kho tại hiện trường
Màn hình Duyệt của phần Quản lý hàng tồn kho tại hiện trường của ứng dụng sẽ hiển thị danh sách các bộ phận cho nồi hơi và hệ thống điều hòa không khí (gọi đơn giản là bộ phận nồi hơi). Màn hình Chi tiết cho phép kỹ thuật viên xem thêm thông tin về bộ phận đã chọn.
Trong cơ sở dữ liệu hàng tồn kho hiện có (có tên là InventoryDB), thông tin về các bộ phận được lưu trữ trong một bảng duy nhất có tên là BoilerParts. Kiana xác định rằng API Web phải hỗ trợ các yêu cầu sau:
- Nhận tất cả các bộ phận của nồi hơi.
- Nhận thông tin chi tiết của một bộ phận, được cung cấp ID bộ phận.
Xác định các hoạt động API Web: Cơ sở kiến thức tại hiện trường
Trong hệ thống hiện tại, cơ sở dữ liệu kiến thức (có tên là KnowledgeDB) chứa ba bảng ghi lại và quản lý mối quan hệ giữa mẹo, kỹ sư và bộ phận:
- Mẹo, chứa thông tin chi tiết về mẹo. Mỗi mẹo bao gồm một bản tóm tắt một dòng xác định một vấn đề cụ thể ( chủ đề) và một lời giải thích chi tiết hơn mô tả cách giải quyết vấn đề ( nội dung). Mỗi mẹo cũng đề cập đến một bộ phận và kỹ sư đã ghi lại mẹo đó.
- BoilerParts, chứa danh sách các bộ phận được tham chiếu theo mẹo. Chi tiết của từng bộ phận được lưu trữ trong bảng BoilerParts trong cơ sở dữ liệu InventoryDB .
- Kỹ sư, liệt kê các kỹ thuật viên đã viết từng mẹo.
Phần cơ sở kiến thức của ứng dụng hiện chỉ chứa một màn hình Trình duyệt giữ chỗ. Maria muốn triển khai chức năng sau:
Kỹ thuật viên chỉ định một thuật ngữ tìm kiếm trên màn hình Duyệt để tìm tất cả các mẹo phù hợp. Sự trùng khớp có thể là tên của bộ phận mà mẹo đề cập đến, văn bản trong chủ đề hay nội dung của mẹo hoặc tên của một kỹ thuật viên là chuyên gia với một thiết bị cụ thể.
Khi tất cả các mẹo phù hợp đã được tìm thấy, kỹ thuật viên có thể chọn một mẹo để xem chi tiết của mẹo đó.
Kỹ thuật viên cũng có thể thêm các mẹo mới vào cơ sở kiến thức, cũng như thêm ghi chú và nhận xét vào các mẹo hiện có.
Cơ sở kiến thức lớn và đang phát triển, và việc truy vấn trên nhiều bảng và cột có thể liên quan đến logic phức tạp đòi hỏi sức mạnh tính toán đáng kể. Để giảm tải cho API Web, Kiana quyết định sử dụng Tìm kiếm nhận thức Azure để cung cấp chức năng tìm kiếm, như đã mô tả trước đó. Để hỗ trợ ứng dụng, Kiana quyết định rằng các hoạt động sau là bắt buộc từ API Web:
Tìm thông tin chi tiết về mẹo trong cơ sở kiến thức được chỉ định từ bảng Mẹo .
Cập nhật mẹo trong cơ sở kiến thức hiện có trong bảng Mẹo .
Thêm mẹo cơ sở kiến thức mới vào bảng Mẹo , cũng có thể bao gồm việc thêm hàng vào bảng BoilerParts và Engineers nếu bộ phận hoặc kỹ sư được chỉ định hiện không có mẹo nào được ghi lại. Quy trình thực sự thực hiện logic đằng sau việc thêm một mẹo mới sẽ được triển khai dưới dạng một ứng dụng logic được gọi từ Power Apps.
Xác định các hoạt động API Web: Lên lịch tại hiện trường
Lên lịch các cuộc hẹn với kỹ thuật viên không chỉ yêu cầu truy vấn, thêm, bớt các cuộc hẹn mà còn phải ghi lại thông tin về khách hàng. Hệ thống cuộc hẹn hiện tại ghi lại dữ liệu này trong ba bảng trong cơ sở dữ liệu SchedulesDB :
- Cuộc hẹn, chứa thông tin chi tiết về mỗi cuộc hẹn, bao gồm ngày, giờ, vấn đề, ghi chú và kỹ thuật viên được giao nhiệm vụ.
- Khách hàng, lưu trữ thông tin chi tiết của từng khách hàng, bao gồm tên, địa chỉ và thông tin liên lạc của họ.
- Kỹ sư, liệt kê từng kỹ thuật viên tham dự cuộc hẹn.
Lưu ý
Cơ sở dữ liệu thực sự chứa một bảng thứ tư có tên là AppointmentsStatus. Bảng này chứa danh sách các giá trị hợp lệ cho trạng thái của một cuộc hẹn và chỉ đơn giản là một tra cứu được sử dụng bởi các phần khác của hệ thống cuộc hẹn hiện có.
Kiana quyết định rằng các thao tác sau sẽ hữu ích cho phần Lên lịch tại hiện trường của ứng dụng:
- Tìm tất cả các cuộc hẹn cho một kỹ thuật viên được chỉ định.
- Tìm tất cả các cuộc hẹn cho ngày hiện tại cho một kỹ thuật viên được chỉ định.
- Tìm cuộc hẹn đã lên lịch tiếp theo cho một kỹ thuật viên được chỉ định.
- Cập nhật thông tin chi tiết của cuộc hẹn, chẳng hạn như thêm ghi chú hoặc ảnh.
- Tìm thông tin chi tiết về khách hàng.
Xây dựng API Web: Quản lý hàng tồn kho tại hiện trường
Các hệ thống hiện có lưu trữ dữ liệu bằng cách sử dụng Cơ sở dữ liệu Azure SQL. Kiana quyết định xây dựng Web API bằng cách sử dụng Entity Framework Core, vì phương pháp này có thể tạo ra rất nhiều mã truy vấn, chèn và cập nhật dữ liệu tự động. Mẫu Web API do Microsoft cung cấp cũng có thể tạo mô tả Swagger mô tả từng thao tác trong API. Những mô tả này rất hữu ích để kiểm tra các hoạt động của API. Nhiều công cụ có thể sử dụng thông tin này để tích hợp API với các dịch vụ khác, chẳng hạn như Quản lý API Azure.
Kiana bắt đầu với chức năng Hàng tồn kho tại hiện trường vì đây là phần đơn giản nhất. Các hoạt động Kiểm kê thực địa trong Web API truy vấn một bảng duy nhất, BoilerParts, trong cơ sở dữ liệu InventoryDB . Bảng này chứa các cột được hiển thị trong hình ảnh sau đây.
Kiana đã áp dụng phương pháp "ưu tiên mã" để xây dựng Web API và thực hiện như sau:
Đã định nghĩa lớp C# model của riêng họ phản ánh cấu trúc của bảng BoilerParts trong cơ sở dữ liệu InventoryDB .
Đã tạo một lớp Entity Framework context mà Web API sử dụng để kết nối với cơ sở dữ liệu, nhằm thực hiện các truy vấn.
Cấu hình lớp ngữ cảnh để kết nối với cơ sở dữ liệu InventoryDB trong Azure.
Sử dụng các công cụ dòng lệnh Entity Framework để tạo lớp điều khiển API Web triển khai các yêu cầu HTTP REST cho từng hoạt động có thể được thực hiện đối với bảng BoilerParts .
Đã sử dụng API Swagger để kiểm tra API Web.
Hình ảnh sau đây cho thấy cấu trúc cấp cao của API Web.
Kiana đã sử dụng quy trình sau để tạo API Web bằng các công cụ dòng lệnh .NET 6.0 và Visual Studio Code:
Mở cửa sổ đầu cuối trong Visual Studio Code.
Chạy lệnh sau để tạo một dự án Web API mới có tên là FieldEngineerApi.
dotnet new webapi -o FieldEngineerApi
Mở thư mục FieldEngineerApi .
Xóa tệp WeatherForecastController.cs bộ điều khiển và WeatherForecast.cs lớp ví dụ được tạo bởi mẫu Web API.
Trong cửa sổ Terminal , thêm các gói và công cụ Entity Framework sau, cùng với hỗ trợ sử dụng SQL Server, vào dự án.
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
Trong thư mục FieldEngineerApi , tạo một thư mục mới có tên là Models.
Trong thư mục Models , tạo một tệp mã C# có tên BoilerPart.cs.
Trong tệp này, hãy thêm các thuộc tính và trường sau. Các thuộc tính và trường này phản ánh cấu trúc của bảng BoilerParts trong cơ sở dữ liệu 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; } } }
Trong thư mục Models , tạo một tệp mã C# khác có tên là InventoryContext.cs. Thêm mã sau vào lớp này. Lớp cung cấp kết nối giữa trình tùy chọn điều khiển (sẽ được tạo tiếp theo) và cơ sở dữ liệu.
using Microsoft.EntityFrameworkCore; namespace FieldEngineerApi.Models { public class InventoryContext : DbContext { public InventoryContext(DbContextOptions<InventoryContext> options) : base(options) { } public DbSet\<BoilerPart\> BoilerParts { get; set; } } }
Chỉnh sửa tệp appsettings.Development.json cho dự án và thêm phần ConnectionStrings với chuỗi kết nối InventoryDB sau. Thay thế <tên máy chủ> bằng tên máy chủ Cơ sở dữ liệu SQL mà bạn đã tạo để lưu trữ cơ sở dữ liệu 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" } } }
Quan trọng
Chỉ dành cho mục đích của hướng dẫn này, chuỗi kết nối chứa ID người dùng và mật khẩu cho cơ sở dữ liệu. Trong hệ thống sản xuất, bạn không bao giờ được lưu trữ các mục này dưới dạng văn bản rõ ràng trong tệp cấu hình.
Chỉnh sửa tệp Startup.cs và thêm các lệnh using sau vào danh sách ở đầu tệp.
using FieldEngineerApi.Models; using Microsoft.EntityFrameworkCore;
Trong lớp Startup , hãy tìm phương thức ConfigureServices . Thêm câu lệnh sau vào phương thức này.
public void ConfigureServices(IServiceCollection services) { services.AddDbContext<InventoryContext>(options => options.UseSqlServer(Configuration.GetConnectionString("InventoryDB"))); services.AddControllers(); ... }
Sửa đổi phương thức Configure và bật Giao diện người dùng Swagger ngay cả khi ứng dụng đang chạy ở chế độ sản xuất, như được hiển thị (thay đổi này liên quan đến việc di chuyển hai lệnh gọi phương thức app.UseSwagger ra bên ngoài câu lệnh if ).
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "FieldEngineerApi v1")); ... }
Quan trọng
Thay đổi này cho phép hiển thị điểm cuối Swagger để tích hợp Quản lý API. Sau khi Quản lý API được cấu hình, bạn nên di chuyển mã này trở lại bên trong câu lệnh if và triển khai lại Web API. Không bao giờ để điểm cuối Swagger mở trong hệ thống sản xuất.
Trong cửa sổ Terminal , hãy chạy lệnh sau để tạo bộ điều khiển BoilerParts từ lớp mô hình BoilerPart và lớp ngữ cảnh InventoryContext .
dotnet aspnet-codegenerator controller ^ -name BoilerPartsController -async -api ^ -m BoilerPart -dc InventoryContext -outDir Controllers
Bộ điều khiển BoilerParts phải được tạo trong thư mục Bộ điều khiển .
[!LƯU Ý] Ký tự kết thúc dòng, ^, chỉ được Windows nhận dạng. Nếu bạn đang chạy Visual Studio Code trên hệ thống Linux, hãy sử dụng ký tự \ thay thế.
Mở tệp BoilerParts.cs trong thư mục Bộ điều khiển và xem lại nội dung của tệp đó. Lớp BoilerPartsController trình bày các phương thức REST sau:
- GetBoilerParts(), trả về danh sách tất cả các đối tượng BoilerPart từ cơ sở dữ liệu.
- GetBoilerPart(long id), dùng để lấy thông tin chi tiết về bộ phận nồi hơi được chỉ định.
- PutBoilerPart(long id, BoilerPart boilerPart), cập nhật một bộ phận nồi hơi trong cơ sở dữ liệu với các chi tiết trong đối tượng BoilerPart được chỉ định làm tham số.
- PostBoilerPart(BoilerPart boilerPart), tạo ra một bộ phận nồi hơi mới.
- DeleteBoilerPart(long id), lệnh này sẽ xóa phần boiler đã chỉ định khỏi cơ sở dữ liệu.
Lưu ý
Ứng dụng của kỹ thuật viên chỉ yêu cầu hai phương thức Get , nhưng các phương thức còn lại hữu ích cho ứng dụng quản lý hàng tồn kho trên máy tính để bàn (không được đề cập trong hướng dẫn này).
Biên dịch và xây dựng API Web.
dotnet build
API Web phải xây dựng mà không báo cáo bất kỳ lỗi hoặc cảnh báo nào.
Triển khai API Web cho Azure: Quản lý hàng tồn kho tại hiện trường
Kiana đã triển khai và thử nghiệm API Web, bằng cách thực hiện các tác vụ sau:
Sử dụng tiện ích bung rộng Tài khoản Azure trong Visual Studio Code, đăng nhập vào đăng ký Azure của bạn.
Từ cửa sổ Terminal trong Visual Studio Code, hãy tạo một nhóm tài nguyên mới có tên webapi_rg trong đăng ký Azure của bạn. Trong lệnh sau, hãy thay thế <vị trí> bằng vùng Azure gần nhất của bạn.
az group create ^ --name webapi_rg ^ --location <location>
Tạo gói Dịch vụ ứng dụng Azure để cung cấp tài nguyên cho việc lưu trữ API Web.
az appservice plan create ^ --name webapi_plan ^ --resource-group webapi_rg ^ --sku F1
Lưu ý
F1 là SKU miễn phí cho các gói Dịch vụ ứng dụng. F1 cung cấp thông lượng và dung lượng hạn chế, và chỉ thích hợp cho các mục đích phát triển.
Tạo ứng dụng web Azure bằng cách sử dụng gói Dịch vụ ứng dụng. Thay thế <tên ứng dụng web> bằng tên duy nhất cho ứng dụng web.
az webapp create ^ --name <webapp name> ^ --resource-group webapi_rg ^ --plan webapi_plan
Trong Visual Studio Mã, hãy chỉnh sửa tệp appSettings.json và thêm chuỗi kết nối giống như chuỗi mà bạn đã ghi trước đó vào tệp appSettings.Development.json . Nhớ thay thế <tên máy chủ> bằng tên máy chủ Cơ sở dữ liệu SQL mà bạn đã tạo để lưu trữ cơ sở dữ liệu 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": "*" }
Trong cửa sổ Đầu cuối, hãy đóng gói API Web đã sẵn sàng để triển khai cho Azure.
dotnet publish -c Release -o ./publish
Lệnh này lưu các tệp đã đóng gói vào một thư mục có tên publish.
Trong Visual Studio Code, nhấp chuột phải vào thư mục publish , sau đó chọn Deploy to Web App.
Chọn tên ứng dụng web mà bạn đã tạo trước đó ở bước 4 (<tên ứng dụng web>). Trong ví dụ sau, ứng dụng web có tên là my-fieldengineer-webapp.
Tại dấu nhắc trong hộp thoại Visual Studio Mã, hãy chọn Triển khai để chấp nhận cảnh báo và triển khai ứng dụng web.
Xác minh rằng ứng dụng web được triển khai thành công, sau đó duyệt đến trang web.
Trang web sẽ mở trong một cửa sổ trình duyệt mới, nhưng sẽ hiển thị lỗi HTTP 404 (không tìm thấy). Điều này là do các hoạt động của Web API có sẵn thông qua điểm cuối api chứ không phải là gốc của trang web. Đổi URL thành https://<tên ứng dụng web>.azurewebsites.net/api/BoilerParts. URI này gọi phương thức GetBoilerParts trong bộ điều khiển BoilerParts . Web API sẽ phản hồi bằng một tài liệu JSON liệt kê tất cả các thành phần của nồi hơi trong cơ sở dữ liệu InventoryDB .
Thay đổi URL trong trình duyệt thành https://<tên ứng dụng web>.azurewebsites.net/swagger. API Swagger sẽ xuất hiện. Đây là giao diện người dùng đồ họa cho phép nhà phát triển xác minh và kiểm tra từng hoạt động trong API Web. Giao diện này cũng hoạt động như một công cụ tài liệu hữu ích.
Chọn GET nằm cạnh điểm cuối /api/BoilerParts/{id} , sau đó chọn Dùng thử.
Trong trường id , nhập ID của một bộ phận, sau đó chọn Thực thi. Hành động này gọi phương thức GetBoilerPart(long id) trong bộ điều khiển BoilerParts . Thao tác này sẽ trả về một tài liệu JSON với các chi tiết của một phần hoặc lỗi HTTP 404 nếu không tìm thấy bộ phận phù hợp trong cơ sở dữ liệu.
Đóng trình duyệt web và quay lại Visual Studio Code.
Xây dựng và triển khai API Web: Cơ sở kiến thức tại hiện trường
Các hoạt động của Field Knowledgebase trong Web API hoạt động trên ba bảng trong cơ sở dữ liệu KnowledgeDB : Tips, BoilerParts và Engineers. Hình ảnh sau đây cho thấy mối quan hệ giữa các bảng này và các cột chứa những bảng đó.
Kiana đã áp dụng cách tiếp cận tương tự cho cơ sở dữ liệu Field Knowledgebase được sử dụng cho cơ sở dữ liệu Field Inventory Management và thực hiện các tác vụ sau:
Tạo các lớp mô hình C# phản ánh cấu trúc của bảng Tips, BoilerParts và Engineers trong cơ sở dữ liệu KnowledgeDB . Mã cho mỗi lớp này được hiển thị như sau.
Lưu ý
Bảng BoilerParts trong cơ sở dữ liệu KnowledgeDB khác với bảng BoilerParts trong cơ sở dữ liệu InventoryDB . Để tránh xung đột tên, các lớp mô hình cho các bảng trong cơ sở dữ liệu KnowledgeDB có tiền tố 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; } } }
Lưu ý
Mã số kỹ sư là một chuỗi, không phải là một số. Điều này là do các hệ thống hiện có sử dụng GUID cho các kỹ thuật viên nhận dạng và những người dùng khác.
// 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; } } }
Tạo một lớp Entity Framework context khác mà Web API sử dụng để kết nối với cơ sở dữ liệu 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; } } }
Chỉnh sửa tệp appsettings.Development.json cho dự án và thêm chuỗi kết nối KnowledgDB sau vào phần ConnectionStrings . Thay thế <tên máy chủ> bằng tên máy chủ Cơ sở dữ liệu SQL mà bạn đã tạo để lưu trữ cơ sở dữ liệu 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": { ... } } }
Quan trọng
Chỉ dành cho mục đích của hướng dẫn này, chuỗi kết nối chứa ID người dùng và mật khẩu cho cơ sở dữ liệu. Trong hệ thống sản xuất, bạn không bao giờ được lưu trữ các mục này dưới dạng văn bản rõ ràng trong tệp cấu hình.
Chỉnh sửa tệp Startup.cs và trong phương thức ConfigureServices , thêm các câu lệnh sau.
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(); ... }
Câu lệnh thứ hai kiểm soát cách dữ liệu được tuần tự hóa khi nó được truy xuất. Một số lớp mô hình có tham chiếu đến các lớp mô hình khác, do đó có thể tham chiếu đến các lớp mô hình khác. Một số tham chiếu này có thể dẫn đến các vòng lặp đệ quy (Thực thể A tham chiếu đến Thực thể B, tham chiếu trở lại Thực thể A, tham chiếu lại Thực thể B, v.v.). Tùy chọn ReferenceLoopHandling khiến trình tuần tự hóa bỏ qua các vòng lặp như vậy trong dữ liệu và chỉ trả về một thực thể và các đối tượng mà nó tham chiếu ngay lập tức, nhưng không trả về gì thêm.
Trong cửa sổ Terminal , hãy chạy lệnh sau để tạo bộ điều khiển từ các lớp mô hình KnowledgeBaseBoilerTip, KnowledgeBaseBoilerPart và KnowledgeBaseEngineer và lớp ngữ cảnh 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
Cả ba bộ điều khiển đều phải được tạo trong thư mục Bộ điều khiển .
Chỉnh sửa tệp KnowledgeBaseBoilerPartController.cs . Tệp này chứa mã cho bộ điều khiển KnowledgeBaseBoilerPart . Nó phải tuân theo cùng một mẫu như lớp BoilerPartsController đã tạo trước đó, hiển thị các phương thức REST cho phép máy khách liệt kê, truy vấn, chèn, cập nhật và xóa các thực thể. Thêm phương thức GetTipsForPart sau vào bộ điều khiển.
[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(); } ... }
Phương thức này trả về tất cả các mẹo cơ sở kiến thức tham chiếu đến một phần cụ thể. Nó truy vấn bảng Mẹo trong cơ sở dữ liệu thông qua đối tượng KnowledgeBaseContext để tìm thông tin này.
Chỉnh sửa tệp KnowledgeBaseEngineerController.cs và thêm phương thức sau vào lớp 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(); } ... }
Phương pháp GetTipsForEngineer tìm tất cả các mẹo trong cơ sở kiến thức do kỹ sư được chỉ định đăng.
Trong cửa sổ Terminal , biên dịch và xây dựng Web API.
dotnet build
API Web phải xây dựng mà không báo cáo bất kỳ lỗi hoặc cảnh báo nào.
Chỉnh sửa tệp appSettings.json và thêm chuỗi kết nối cho cơ sở dữ liệu KnowledgeDB . Chuỗi này phải giống với chuỗi mà bạn đã ghi trước đó vào tệp 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": "*" }
Trong cửa sổ Terminal , hãy đóng gói Web API để sẵn sàng triển khai lên Azure.
dotnet publish -c Release -o ./publish
Trong Visual Studio Code, nhấp chuột phải vào thư mục publish , sau đó chọn Deploy to Web App. Triển khai cùng một ứng dụng web Azure mà bạn đã tạo trước đó. Cho phép trình hướng dẫn ghi đè ứng dụng web hiện có bằng mã mới.
Khi triển khai hoàn tất, hãy duyệt đến trang web nhưng hãy thay đổi URL trong trình duyệt thành https://<tên ứng dụng web>.azurewebsites.net/swagger. Các hoạt động cho bộ điều khiển KnowledgeBaseBoilerPart, KnowledgeBaseEngineer và KnowldgeBaseTip phải được liệt kê ngoài các hoạt động BoilerParts hiện có. Xác minh rằng các hoạt động KnowledgeBaseBoilerPart bao gồm hoạt động GET cho URI /api/KnowledgeBaseBoilerPart/{id}/Tips và các hoạt động KnowledgeBaseEngineer bao gồm hoạt động GET cho URI /api/KnowledgeBaseEngineer/{id}/Tips.
Xây dựng và triển khai API Web: Lên lịch tại hiện trường
Các hoạt động Lên lịch tại hiện trường sử dụng các bảng Cuộc hẹn, Trạng thái cuộc hẹn (đây là bảng tra cứu đơn giản liệt kê các giá trị trạng thái cuộc hẹn hợp lệ), Khách hàng và Kỹ sư, được hiển thị trong hình ảnh sau. Các bảng này được lưu trữ trong cơ sở dữ liệu SchedulesDB .
Để tạo các hoạt động API Web cho phần Lên lịch tại hiện trường của hệ thống, Kiana đã thực hiện các tác vụ sau:
Tạo các lớp mô hình C# phản ánh cấu trúc của bảng AppointmentStatus, Appointments, Customers và Engineers trong cơ sở dữ liệu SchedulesDB . Đoạn mã sau đây hiển thị từng lớp này.
Lưu ý
Lớp mô hình cho bảng Engineers được đặt tên là ScheduleEngineer để phân biệt với mô hình cho bảng Engineers trong cơ sở dữ liệu 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; } } }
Tạo một lớp Entity Framework context mà Web API sử dụng để kết nối với cơ sở dữ liệu 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; } } }
Chỉnh sửa tệp appsettings.Development.json cho dự án và thêm chuỗi kết nối SchedulesDB sau vào phần ConnectionStrings . Thay thế <tên máy chủ> bằng tên máy chủ Cơ sở dữ liệu SQL mà bạn đã tạo để lưu trữ cơ sở dữ liệu 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": { ... } } }
Chỉnh sửa tệp Startup.cs và trong phương thức ConfigureServices , thêm câu lệnh sau.
public void ConfigureServices(IServiceCollection services) { services.AddDbContext<InventoryContext>...; services.AddDbContex\<KnowledgeBaseContext>...; services.AddDbContext<ScheduleContext>(options => options.UseSqlServer(Configuration.GetConnectionString("SchedulesDB"))); services.AddControllers().AddNewtonsoftJson(...); ... }
Trong cửa sổ Terminal , hãy chạy lệnh sau để tạo bộ điều khiển từ các lớp mô hình Appointment, Customer và ScheduleEngineer và lớp ngữ cảnh ScheduleContext .
Lưu ý
Không tạo bộ điều khiển riêng cho mô hình 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
Chỉnh sửa tệp AppointmentsController.cs . Trong lớp AppointmentsController , hãy tìm phương thức GetAppointments . Sửa đổi câu lệnh return như được hiển thị. Thay đổi này đảm bảo rằng thông tin Khách hàng, Kỹ sư và Trạng thái cuộc hẹn được truy xuất như một phần của hoạt động GET ; các trường này tham chiếu đến các thực thể khác mà nếu không sẽ bị bỏ trống do cơ chế tải chậm của 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(); } ... }
Trong cùng một tệp, hãy sửa đổi phương thức GetAppointment(long id) như được hiển thị.
// 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; }
Phiên bản phương pháp này sẽ điền các trường Khách hàng, Kỹ sư và Trạng thái cuộc hẹn của một cuộc hẹn khi nó được truy xuất (nếu không, tải chậm sẽ để trống các trường này).
Tìm phương thức PutAppointment và thay thế bằng mã sau. Phiên bản phương thức PutAppointment này sử dụng các trường trong một cuộc hẹn mà người dùng có thể sửa đổi trong ứng dụng thay vì một đối tượng Appointment hoàn chỉnh.
[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(); }
Lưu ý
Theo nguyên tắc chung, các hoạt động PUT chỉ nên sửa đổi dữ liệu mà người dùng được phép cập nhật, không nhất thiết là mọi trường trong một thực thể.
Mở tệp ScheduleEngineerController.cs và thêm phương thức GetScheduleEngineerAppointments sau vào lớp 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.
Chỉnh sửa tệp CustomerController.cs và thêm các phương thức GetAppointments và GetNotes như được hiển thị, vào lớp 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(); } ... }
Phương thức GetAppointments tìm tất cả các cuộc hẹn cho khách hàng đã chỉ định. Phương pháp GetNotes sẽ lấy lại tất cả các ghi chú mà kỹ thuật viên đã ghi lại trong những lần đến thăm khách hàng trước đó.
Chỉnh sửa tệp appSettings.json và thêm chuỗi kết nối cho cơ sở dữ liệu KnowledgeDB . Chuỗi này phải giống với chuỗi mà bạn đã ghi trước đó vào tệp 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": "*" }
Trong cửa sổ Terminal , biên dịch và xây dựng Web API.
dotnet build
API Web phải xây dựng mà không báo cáo bất kỳ lỗi hoặc cảnh báo nào.
Trong cửa sổ Terminal , hãy đóng gói Web API để sẵn sàng triển khai lên Azure.
dotnet publish -c Release -o ./publish
Trong Visual Studio Code, nhấp chuột phải vào thư mục publish , sau đó chọn Deploy to Web App. Triển khai cùng một ứng dụng web Azure mà bạn đã tạo trước đó. Cho phép trình hướng dẫn ghi đè ứng dụng web hiện có bằng mã mới.
Khi triển khai hoàn tất, hãy duyệt đến trang web nhưng hãy thay đổi URL trong trình duyệt thành https://<tên ứng dụng web>.azurewebsites.net/swagger. Xác minh rằng các hoạt động dành cho bộ điều khiển Cuộc hẹn, Khách hàng và ScheduleEngineer hiện đã khả dụng.
API Web hiện đã sẵn sàng để được tích hợp vào ứng dụng.