
ModelState מורכב, והסרטון מפרק אותו כדי לשלוף ממנו את הודעות השגיאה האמיתיות ולהחזיר אותן ללקוח, וגם מראה איך להפוך את הקוד לפונקציית הרחבה שאפשר להשתמש בה בכל controller.string, ומקבלת ModelStateDictionary (המאפיין ModelState ב-controller נשלח אליה).string עם שם המאפיין, וה-value הוא ModelStateEntry. בלולאת foreach רואים רק מאפיינים שנכשלו בוולידציה: כשלא היו title ו-price תקין, הקונסול הציג את שניהם ולא את description.Errors, כי מאפיין אחד יכול להיכשל בכמה בדיקות (למשל max length וגם אות גדולה). לולאה פנימית על value.errors נותנת ErrorMessage לכל שגיאה.errors ריק, מוסיפים כל ErrorMessage עם רווח, ומחזירים עם Trim. התוצאה "Book price must be zero to 100. Missing book title." מוחזרת ב-BadRequest במקום something bad.utils (קודם Helper), שחייבת להיות static, כדי לקרוא לה מכל controller.this: כשמוסיפים this לפני הפרמטר, אפשר לכתוב ModelState.GetAllErrors() במקום Helper.GetAllErrors(ModelState). זה Extension Function, ו"קסם של ה-compiler" מחליף את הקריאה. לכן שינו את שם המחלקה ל-Extensions.GetFirstError מחזירה רק שגיאה אחת, כך שהשרת עובד מהר יותר והלקוח מתקן ומנסה שוב. אפשר גם בשורה אחת: ModelState.Values.Where(...) שיש להם errors, אחר כך First ו-ErrorMessage. הבדיקה נחוצה כי נתקלו ב-value בלי errors.UpdateBookPrice (patch) נכשל על title שחסר. הפתרון שהמרצה מצא הוא ModelState.Remove על title ועל description, ונשאר רק price. הוא מציין שזה לא אלגנטי ושלכן פחות מתכנתים אוהבים patch. אפשר גם לבדוק את המחיר ידנית, אבל זה משכפל בדיקות.Delete אין צורך כי מקבלים רק ID.הטקסט המלא של הדקות הראשונות בהרצאה «הוצאת הודעות השגיאה מתוך ModelState» בקורס הווידאו של PracticU – כתוביות בעברית עם זמן התחלה לכל פסקה. כך תוכלו לקרוא ולחפש את הנושאים לפני שמתחילים ללמוד.
אז כמו שאמרתי, המאפיין הזה model state שמגיע אלינו מהקונטרולר base הזה הוא קצת מסועף, אה, קצת מורכב וצריך להבין מיהו, מהו, מה יש בתוכו בשביל לדעת איך לחלץ ממנו את השגיאות.
בואו נעשה איזושהי פונקציית עזר קטנטנה כאן. זה לא המקום הנכון לכתוב אותה, אני רק רוצה שהיא תהיה מאוד מאוד קרובה לאזור הזה וכמובן תכף נעביר אותה למקום אחר. נבנה פונקציה קטנטנה, בואו נקרא לה, אמ, private נניח string, היא מחזירה string ונגיד תביא לי את כל השגיאות.
אני רוצה לקבל את אותו, אמ, מאפיין כאן לפונקציה, להחזיר את כל השגיאות כולן שיש במאפיין הזה כמחרוזת אחת ארוכה שמכילה את כל השגיאות. אז הסוג של הדבר הזה, אם אנחנו מרחפים עליו אנחנו רואים שהסוג שלו, רואים את זה כאן, הוא model state dictionary.
אוקיי, מעולה. אז בואו נכתוב פה model state dictionary ונקרא לו model state עם m קטנה, כי זה משתנה לוקאלי של הפונקציה. המאפיין נקרא Model State עם M גדולה, אבל אפשר עכשיו לשלוח את הדבר הזה, Model State עם M גדולה, לפה, ל-model state עם m קטנה והוא יחזיר לנו כאן את כל הודעות השגיאה שקיימות בתוכו.
מה זה dictionary? Dictionary זה collection שבו כל פריט מכיל key ו-value. אוקיי? key ייחודי ואיזשהו value שמתאר משהו.
אז איך אנחנו מחזירים את כל השגיאות? דבר ראשון בואו ניקח string errors ונתחיל אותו במחרוזת ריקה. בסוף בסוף אנחנו רוצים to return errors בצורה כזאת, ומבין לבין אנחנו רוצים לרוץ על ה-collection הזה, זה סך הכול collection, ולאסוף ממנו את כל השגיאות.
איך אני רץ על collection של dictionary? For each. כל פריט ב-collection זה בעצם item ואני רוצה שהוא יהיה, שהוא ירוץ על ה-model state הזה שפה.
אז אם אני עכשיו בא ואומר לו model state ככה, אז בעצם זאת לולאה חוקית שרצה collection, כי על כל collection אפשר לרוץ בלולאת for each. מה זה item?
item יש key ו-value. אנחנו צריכים להבין מה זה בעצם ה-key ומה זה ה-value. אז ה-key זה סך הכול string. בואו נסתכל item נקודה key אומר לי שזה string וה-value זה איזשהו אובייקט שנקרא model state entry.
זה בעצם פריט שנמצא בתוך ה-dictionary הזה ומתאר property במודל שנכשל. אם יש לי property ששולחים והוא לא נכשל בוולידציה, אז הוא בכלל בכלל לא יהיה בתוך ה-dictionary הזה.
זאת אומרת שה-dictionary הזה כולל רק פריטים שנכשלו. בואו ננסה רגע לעשות כזה דבר. נריץ את item נקודה key, כי זה string, מאוד קל לראות stringים על הקונסול.
כאן פשוט נשלח לפונקציה get all errors, נשלח לה את ה-model state שלנו בצורה כזאת ואז היא תציג לנו על המסך רק את המאפיינים שנכשלו. בואו ננסה.
ניגש-- קודם כל נריץ כמובן וניגש ל-postman