הערה
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות להיכנס או לשנות מדריכי כתובות.
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות לשנות מדריכי כתובות.
לאחר שקבעו שהנתונים עבור יישום הטכנאים צריכים להגיע ממערכות קיימות דרך Web API, הדסה ושירה עובדות ביחד כדי לקבוע בדיוק איזה מידע דרוש, ובאיזו תבנית. שירה תיצור לאחר מכן יישום אינטרנט שחושף את ה- Web API המתאים ותתאם אירוח שלו ב- Azure. היישום יכול להתחבר ל- Azure מכל מקום שבו יש חיבור אלחוטי.
הגדרת פעולות ה- Web API: ניהול מלאי שדה
המסך עיון של המקטע 'ניהול מלאי שדה' של היישום מציג רשימת חלקים עבור דוודים ומערכות מיזוג אוויר (מכונה בפשטות חלקי דוד). המסך פרטים מאפשר לטכנאי להציג מידע נוסף אודות חלק נבחר.
במסד הנתונים של המלאי הקיים (נקרא InventoryDB), המידע אודות חלקים נשמר בטבלה יחידה בשם BoilerParts. שירה קובעת שה- Web API אמור לתמוך בבקשות הבאות:
- קבל את כל חלקי הדוד.
- קבל את פרטי החלק, בהתחשב במזהה החלק.
הגדרת פעולות ה- Web API: מאגר ידע של שטח
במערכת הקיימת, מסד הנתונים של מאגר הידע (בשם KnowledgeDB) מכיל שלוש טבלאות המתעדות ומנהלות את הקשרים בין עצות, מהנדסים וחלקים:
- עצות, שמכיל את פרטי העצה. כל עצה מורכבת מסיכום בן שורה יחידה המזהה בעיה מסוימת (הנושא) והסבר מפורט יותר המתאר כיצד לפתור את הבעיה (הגוף). כל עצה גם מפנה לחלק ולמהנדס שתיעד את העצה.
- חלקי דוד, שמכיל רשימה של החלקים שמפנות אליהם עצות. פרטי החלקים עצמם מאוחסנים בטבלה חלקי דוד במסד הנתונים InventoryDB.
- מהנדסים, המפרט את הטכנאים שחיברו כל עצה.
חלק מאגר הידע של היישום מכיל כעת רק מסך דפדפן שהוא מציין מיקום. הדסה רוצה ליישם את הפונקציונליות הבאה:
הטכנאי מציין מונח חיפוש במסך עיון כדי למצוא את כל העצות המתאימות. ההתאמה יכולה להיות בשם החלק אליו שאליו מתייחסת העצה, טקסט בנושא או בגוף העצה או שם הטכנאי המומחה לחלק ציוד ספציפי.
לאחר שנמצאו כל העצות המתאימות, הטכנאי יכול לבחור עצה כדי להציג את פרטיה.
טכנאי יכול גם להוסיף עצות חדשות למאגר הידע, וכן להוסיף הערות לעצות קיימות.
מאגר הידע הוא גדול והולך וגדל, וביצוע השאילתות על טבלאות ועמודות מרובות יכול להיות כרוך בלוגיקה מורכבת הדורשת עוצמת מחשוב ניכרת. כדי להפחית את העומס על ה- Web API, שירה מחליטה להשתמש ב- Azure Cognitive Search כדי לספק את פונקציונליות החיפוש, כמתואר קודם לכן. כדי לתמוך ביישום, שירה מחליטה שהפעולות הבאות נדרשות מה- Web API:
למצוא את הפרטים של עצת מאגר ידע ספציפית מהטבלה עצות.
לעדכן עצה קיימת של מאגר ידע בטבלה עצות.
להוסיף עצה חדשה של מאגר ידע לטבלה עצות, מה שעשוי להיות כרוך גם בהוספת שורות לטבלאות חלקי דוד ומהנדסים אם החלק או המהנדס שצוין אינו כולל כעת עצות שתועדו עבורו. השגרה שמבצעת בפועל את הלוגיקה שמאחורי הוספת עצה חדשה תיושם כיישום לוגי מתוך Power Apps.
הגדרת פעולות ה- Web API: תזמון בשטח
תזמון פגישות טכנאי דורש לא רק ביצוע שאילתות, הוספה והסרה של פגישות, אלא גם תיעוד מידע אודות לקוחות. מערכת הפגישות הקיימת מתעדת נתונים אלה בשלוש טבלאות במסד הנתונים SchedulesDB:
- פגישות, שמכיל את הפרטים של כל פגישה, כולל התאריך, השעה, הבעיה, ההערות והטכנאי המוקצה למשימה.
- לקוחות, שמכיל את הפרטים של כל לקוח, כולל שמו, כתובתו ופרטי הקשר שלו.
- מהנדסים, המפרט כל טכנאי המשתתף בפגישות.
הערה
מסד הנתונים מכיל למעשה טבלה רביעית בשם AppointmentsStatus. טבלה זו מכילה רשימה של ערכים חוקיים עבור מצב הפגישה והיא פשוט בדיקת מידע המשמשת חלקים אחרים במערכת הפגישות הקיימת.
שירה מחליטה שהפעולות הבאות יהיו שימושיות עבור החלק 'תזמון בשטח' של היישום:
- מציאת כל הפגישות עבור טכנאי שצוין.
- מציאת כל הפגישות לאותו יום עבור טכנאי שצוין.
- מציאת הפגישה המתוכננת הבאה עבור טכנאי שצוין.
- עדכון פרטי הפגישה, כגון הוספת הערות או תצלום.
- מציאת פרטים אודות לקוח.
בניית ה- Web API: ניהול מלאי שדה
המערכות הקיימות שומרות נתונים באמצעות Azure SQL Database. שירה מחליטה לבנות את ה- Web API באמצעות Entity Framework Core, מכיוון שגישה זו יכולה ליצור חלק גדול מהקוד שמבצע שאילתות, מוסיף ומעדכן נתונים באופן אוטומטי. תבנית ה- Web API שסיפקה Microsoft יכולה גם ליצור את תיאורי Swagger שמתארים כל פעולה ב- API. תיאורים אלה שימושיים לבדיקת פעולות ה- API. כלים רבים יכולים להשתמש במידע זה כדי לשלב את ה- API עם שירותים אחרים, כגון ניהול API של Azure.
שירה התחילה עם הפונקציונליות של מלאי השדה מכיוון שזה החלק הפשוט ביותר. פעולות מלאי השדה ב- Web API מבצעות שאילתה בטבלה יחידה, חלקי דוד, במסד הנתונים InventoryDB. טבלה זו מכילה את העמודות המוצגות בתמונה הבאה.
שירה נקטה בגישת "קוד תחילה" לבניית ה- Web API, וביצעה את הפעולות הבאות:
הגדירה את מחלקת C# model ששיקפה את המבנה של הטבלה BoilerParts במסד הנתונים InventoryDB .
יצרה מחלקת הקשר של Entity Framework שה- Web API משתמש בה כדי להתחבר למסד הנתונים לצורך ביצוע שאילתות.
קבעה את תצורת מחלקת ההקשר להתחברות אל מסד הנתונים InventoryDB ב- Azure.
השתמשה בכלי שורת הפקודה של Entity Framework כדי ליצור מחלקת בקר של Web API שמיישמת בקשות HTTP REST עבור כל אחת מהפעולות שניתן לבצע כנגד הטבלה חלקי דוד.
השתמשה ב- API של Swagger לבדיקת ה- Web API.
התמונה הבאה מציגה את המבנה ברמה הגבוהה של ה- Web API.
שירה השתמשה בהליך הבא כדי ליצור את ה- Web API באמצעות כלי שורת פקודה של .NET 6.0 ו- Visual Studio Code:
פתיחת חלון מסוף ב- Visual Studio Code.
הפעלת הפקודה הבאה ליצור פרוייקט Web API חדש בשם FieldEngineerApi.
dotnet new webapi -o FieldEngineerApi
פתיחת התיקיה FieldEngineerApi.
הסרת הבקר WeatherForecastController.cs לדוגמה ואת קובץ המחלקה של WeatherForecast.cs שנוצר על-ידי תבנית Web API.
בחלון מסוף, הוסף את החבילות והכלים הבאים של 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
בתיקיה FieldEngineerApi, צור תיקיה חדשה בשם מודלים.
בתיקיה מודלים, צור קובץ קוד C# בשם BoilerPart.cs.
בקובץ זה, הוסף את המאפיינים והשדות הבאים. מאפיינים ושדות אלה משקפים את מבנה הטבלה חלקי דוד במסד הנתונים 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; } } }
בתיקיה מודלים, צור קובץ קוד 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; } } }
ערוך את הקובץ appsettings.Development.json עבור הפרוייקט, והוסף מקטע ConnectionStrings עם מחרוזת החיבור InventoryDB הבאה. החלף את <server name> בשם שרת SQL Database שיצרת כדי לשמור את מסד הנתונים 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" } } }
חשוב
למטרות מדריך זה בלבד, מחרוזת החיבור מכילה את מזהה המשתמש והסיסמה עבור מסד הנתונים. במערכת ייצור, אין לאחסן פריטים אלה בטקסט ברור בקובץ תצורה.
ערוך את הקובץ Startup.cs והוסף את הנחיות השימוש הבאות לרשימה בתחילת הקובץ.
using FieldEngineerApi.Models; using Microsoft.EntityFrameworkCore;
במחלקה אתחול, מצא את פעולת השירות ConfigureServices. הוסף את ההצהרות הבאות לפעולת שירות זו.
public void ConfigureServices(IServiceCollection services) { services.AddDbContext<InventoryContext>(options => options.UseSqlServer(Configuration.GetConnectionString("InventoryDB"))); services.AddControllers(); ... }
שנה את פעולת השירות קביעת תצורה והפעל את ממשק המשתמש של Swagger גם כאשר היישום פועל במצב ייצור, כפי שמוצג (שינוי זה כרוך במיקום מחדש של שתי הקריאות לפעולת השירות app.UseSwagger מחוץ להצהרה 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")); ... }
חשוב
שינוי זה מאפשר לנקודת הקצה של Swagger להיחשף עבור שילוב ניהול API. לאחר הגדרת ניהול API, עליך להעביר קוד זה בחזרה לתוך ההצהרה if ולפרוס מחדש את ה- Web API. לעולם אל תשאיר נקודת קצה של Swagger פתוחה במערכת ייצור.
בחלון מסוף, הפעל את הפקודה הבאה כדי ליצור את הבקר חלקי דוד ממחלקת המודל חלק דוד ומחלקת ההקשר InventoryContext.
dotnet aspnet-codegenerator controller ^ -name BoilerPartsController -async -api ^ -m BoilerPart -dc InventoryContext -outDir Controllers
יש ליצור את הבקר חלקי דוד בתיקיה בקרים.
[!NOTE] התו מסיים השורה, ^, מזוהה רק על-ידי Windows. אם אתה מפעיל את Visual Studio Code במערכת Linux, השתמש במקום זאת בתו \.
פתח את הקובץ BoilerParts.cs בתיקיה בקרים וסקור את תוכנה. המחלקה BoilerPartsController חושפת את פעולות השירות של REST הבאות:
- GetBoilerParts(), שמחזירה רשימה של כל אובייקטי חלק דוד ממסד הנתונים.
- GetBoilerPart(long id), שמאחזרת את הפרטים של חלק הדוד שצוין.
- PutBoilerPart(long id, BoilerPart boilerPart), שמעדכנת חלק דוד במסד הנתונים עם הפרטים באובייקט חלק דוד שצוין כפרמטר.
- PostBoilerPart(BoilerPart boilerPart), שיוצרת חלק דוד חדש.
- DeleteBoilerPart(long id), שמסירה את חלק הדוד שצוין ממסד הנתונים.
הערה
יישום הטכנאי דורש רק את שתי פעולות השירות מסוג Get, אבל האחרות שימושיות ליישום ניהול המלאי של שולחן העבודה (לא נכלל במדריך זה).
הדר ובנה את ה- Web API.
dotnet build
ה- Web API אמור להיבנות מבלי לדווח על שגיאות או אזהרות.
פריסת ה- Web API ב- Azure: ניהול מלאי שדה
שירה פרסה ובדקה את ה- Web API, על-ידי ביצוע המשימות הבאות:
באמצעות הרחבת חשבון Azure ב- Visual Studio Code, היכנס למנוי Azure שלך.
מהחלון 'מסוף' ב- Visual Studio Code, צור קבוצת משאבים חדשה בשם webapi_rg במנוי Azure שלך. בפקודה הבאה, החלף את <location> עם אזור Azure הקרוב ביותר שלך.
az group create ^ --name webapi_rg ^ --location <location>
צור תוכנית שירות יישום Azure כדי לספק את המשאבים לאירוח ה- Web API.
az appservice plan create ^ --name webapi_plan ^ --resource-group webapi_rg ^ --sku F1
הערה
F1 הוא ה- SKU בחינם עבור תוכניות שירות יישומים. הוא מספק תפוקה וקיבולת מוגבלות, ומתאים אך ורק למטרות פיתוח.
צור יישום אינטרנט של Azure באמצעות תוכנית שירות היישום. החלף את <webapp name> עם שם ייחודי עבור יישום האינטרנט.
az webapp create ^ --name <webapp name> ^ --resource-group webapi_rg ^ --plan webapi_plan
ב- Visual Studio Code, ערוך את הקובץ appSettings.json והוסף את אותה מחרוזת חיבור שכתבת קודם לכן בקובץ appSettings.Development.json. זכור להחליף את <server name> בשם שרת SQL Database שיצרת כדי לשמור את מסד הנתונים 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": "*" }
בחלון 'מסוף', ארוז את ה- Web API המוכן לפריסה ל- Azure.
dotnet publish -c Release -o ./publish
פקודה זו שומרת את הקבצים הארוזים בתיקיה בשם פרסום.
ב- Visual Studio Code, לחץ באמצעות לחצן העכבר הימני על התיקיה פרסום ולאחר מכן בחר את פרוס ליישום אינטרנט.
בחר את שם יישום האינטרנט שיצרת קודם לכן בשלב 4 (<webapp name>). בדוגמה הבאה, יישום האינטרנט נקרא my-fieldengineer-webapp.
בהנחיה בתיבת הדו-שיח של Visual Studio Code, בחר פריסה כדי לקבל את האזהרה ולפרוס את יישום האינטרנט.
ודא שיישום האינטרנט נפרס בהצלחה, ולאחר מכן עבור אל אתר האינטרנט.
אתר האינטרנט ייפתח בחלון דפדפן חדש, אך יציג שגיאת HTTP 404 (לא נמצא). הסיבה לכך היא שפעולות ה- Web API זמינות דרך נקודת הקצה api ולא דרך שורש אתר האינטרנט. שנה את כתובת ה- URL ל- https://<webapp name>.azurewebsites.net/api/BoilerParts. URI זה מפעיל את פעולת השירות GetBoilerParts בבקר BoilerParts. ה- Web API אמור להגיב עם מסמך JSON המפרט את כל חלקי הדוד במסד הנתונים InventoryDB.
שנה את כתובת ה- URL בדפדפן ל- https://<webapp name>.azurewebsites.net/swagger. ה- API של Swagger אמור להופיע. זהו ממשק משתמש גרפי המאפשר למפתח לאמת ולבדוק כל אחת מהפעולות ב- Web API. הוא משמש גם ככלי תיעוד שימושי.
בחר GET בסמוך לנקודת הקצה של /api/BoilerParts/{id} ולאחר מכן בחר נסה את זה.
בשדה מזהה, הזן את מזהה החלק ובחר בצע. פעולה זו קוראת לפעולת השירות GetBoilerPart(long id) בבקר BoilerParts. היא תחזיר מסמך JSON עם פרטי החלק או שגיאת HTTP 404 אם לא נמצא חלק מתאים במסד הנתונים.
סגור את דפדפן האינטרנט וחזור אל Visual Studio Code.
בנייה ופריסה של ה- Web API: מאגר ידע של שטח
פעולות מאגר הידע של השטח ב- Web API פועלות בשלוש טבלאות במסד הנתונים KnowledgeDB: עצות, חלקי דוד, ומהנדסים. התמונה הבאה מציגה את הקשרים בין הטבלאות הללו ואת העמודות שהן מכילות.
שירה אימצה גישה דומה עבור מסד הנתונים 'מאגר ידע של שטח', מסד נתונים ששימש כמסד הנתונים 'ניהול מלאי שדה' וביצעה את המשימות הבאות:
צור מחלקות מודל C# המשקפות את מבנה הטבלה עצות, חלקי דוד, ומהנדסים במסד הנתונים KnowledgeDB. הקוד עבור כל אחת מהמחלקות הללו מוצג להלן.
הערה
הטבלה חלקי דוד במסד הנתונים KnowledgeDB נבדלת מהטבלה חלקי דוד במסד הנתונים 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; } } }
הערה
מזהה המהנדס הוא מחרוזת ולא מספר. הסיבה לכך היא שהמערכות הקיימות משתמשות במזהי 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; } } }
צור מחלקת הקשר אחרת של 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; } } }
ערוך את הקובץ appsettings.Development.json עבור הפרוייקט, והוסף את מחרוזת החיבור KnowledgeDB הבאה למקטע ConnectionStrings. החלף את <server name> בשם שרת SQL Database שיצרת כדי לשמור את מסד הנתונים 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": { ... } } }
חשוב
למטרות מדריך זה בלבד, מחרוזת החיבור מכילה את מזהה המשתמש והסיסמה עבור מסד הנתונים. במערכת ייצור, אין לאחסן פריטים אלה בטקסט ברור בקובץ תצורה.
ערוך את הקובץ 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 גורמת לעורך בסידרה להתעלם מלולאות כאלה בנתונים, ולהחזיר רק ישות ואת האובייקטים שהיא מפנה אליהם באופן מיידי, ותו לא.
בחלון מסוף, הפעל את הפקודה הבאה כדי ליצור בקרים ממחלקות המודל 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
יש ליצור את כל שלושת הבקרים בתיקיה בקרים.
ערוך את הקובץ 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 כדי למצוא מידע זה.
ערוך את הקובץ 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 מוצאת את כל עצות מאגר הידע שפורסמו על-ידי המהנדס שצוין.
בחלון מסוף, בצע הידור ובנה את ה- Web API.
dotnet build
ה- Web API אמור להיבנות מבלי לדווח על שגיאות או אזהרות.
ערוך את הקובץ 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": "*" }
בחלון מסוף, ארוז את ה- Web API המוכן לפריסה ל- Azure.
dotnet publish -c Release -o ./publish
ב- Visual Studio Code, לחץ באמצעות לחצן העכבר הימני על התיקיה פרסום ולאחר מכן בחר את פרוס ליישום אינטרנט. פרוס לאותו יישום אינטרנט של Azure שיצרת קודם לכן. אפשר לאשף להחליף את יישום האינטרנט הקיים בקוד החדש.
לאחר שהפריסה הסתיימה, עבור אל אתר האינטרנט, אבל שנה את כתובת ה- URL בדפדפן ל- https://<webapp name>.azurewebsites.net/swagger. הפעולות עבור הבקרים KnowledgeBaseBoilerPart, KnowledgeBaseEngineer, ו- KnowldgeBaseTip אמורות להופיע בנוסף לפעולות חלקי דוד הקיימות. ודא שהפעולות KnowledgeBaseBoilerPart כוללות פעולת GET עבור ה- URI /api/KnowledgeBaseBoilerPart/{id}/Tips, והפעולות KnowledgeBaseEngineer כוללות פעולת GET עבור ה- URI /api/KnowledgeBaseEngineer/{id}/Tips.
בנייה ופריסה של ה- Web API: תזמון בשטח
פעולות 'תזמון בשטח' משתמשות בטבלאות פגישות, AppointmentStatuses (זוהי טבלת בדיקת מידע פשוטה המפרטת את ערכי מצב הפגישה החוקיים), לקוחות ומהנדסים, המוצגות בתמונה הבאה. טבלאות אלה מאוחסנות במסד הנתונים SchedulesDB.
כדי ליצור את פעולות Web API עבור החלק 'תזמון בשטח' של המערכת, שירה ביצעה את המשימות הבאות:
יצרה מחלקות מודל 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; } } }
צור מחלקת הקשר של 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; } } }
ערוך את הקובץ appsettings.Development.json עבור הפרוייקט, והוסף את מחרוזת החיבור SchedulesDB הבאה למקטע ConnectionStrings. החלף את <server name> בשם שרת SQL Database שיצרת כדי לשמור את מסד הנתונים 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": { ... } } }
ערוך את הקובץ 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(...); ... }
בחלון מסוף, הפעל את הפקודה הבאה כדי ליצור בקרים ממחלקות המודל פגישה, לקוח ו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
ערוך את הקובץ AppointmentsController.cs. במחלקה AppointmentsController, מצא את פעולת השירות GetAppointments. שנה את ההצהרה return, כפי שמוצג. שינוי זה מוודא שמידע לקוח, מהנדס ו- 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(); } ... }
באותו קובץ, שנה את פעולת השירות 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 של פגישה כאשר היא מאוחזרת (טעינה עצלה תשאיר שדות אלה ריקים בכל מקרה אחר).
מצא את פעולת השירות 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 צריכות לשנות רק נתונים שיש לאפשר למשתמש לעדכן, ולאו דווקא כל שדה בישות.
פתח את הקובץ 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.
Edit the CustomerController.cs file and add the GetAppointments and GetNotes methods, as shown, to the CustomerController class.
[Route("api/[controller]")] [ApiController] public class CustomerController : ControllerBase { private readonly ScheduleContext _context; public CustomerController(ScheduleContext context) { _context = context; } //GET: api/Customers/5/Appointments [HttpGet("{id}/Appointments")] public async Task<ActionResult<IEnumerable<Appointment>>> GetAppointments(long id) { return await _context.Appointments .Where(a => a.CustomerId == id) .OrderByDescending(a => a.StartDateTime) .ToListAsync(); } //GET: api/Customers/5/Notes [HttpGet("{id}/Notes")] public async Task<ActionResult<IEnumerable<object>>> GetNotes(long id) { return await _context.Appointments .Where(a => a.CustomerId == id) .OrderByDescending(a => a.StartDateTime) .Select(a => new {a.StartDateTime, a.ProblemDetails, a.Notes}) .ToListAsync(); } ... }
פעולת השירות GetAppointments מוצאת את כל הפגישות עבור הלקוח שצוין. פעולת השירות GetNotes מאחזרת את כל ההערות שהטכנאי הוסיף בביקורים קודמים ללקוח.
ערוך את הקובץ 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": "*" }
בחלון מסוף, בצע הידור ובנה את ה- Web API.
dotnet build
ה- Web API אמור להיבנות מבלי לדווח על שגיאות או אזהרות.
בחלון מסוף, ארוז את ה- Web API המוכן לפריסה ל- Azure.
dotnet publish -c Release -o ./publish
ב- Visual Studio Code, לחץ באמצעות לחצן העכבר הימני על התיקיה פרסום ולאחר מכן בחר את פרוס ליישום אינטרנט. פרוס לאותו יישום אינטרנט של Azure שיצרת קודם לכן. אפשר לאשף להחליף את יישום האינטרנט הקיים בקוד החדש.
לאחר שהפריסה הסתיימה, עבור אל אתר האינטרנט, אבל שנה את כתובת ה- URL בדפדפן ל- https://<webapp name>.azurewebsites.net/swagger. ודא שהפעולות עבור הבקרים פגישות, לקוח ו- ScheduleEngineer זמינות כעת.
ה- Web API מוכן כעת לשילוב ביישום.