บทความชุด .NET 6,7 แบบจับมือทำ — #6:Configuration

Ponggun
T. T. Software Solution
5 min readFeb 18, 2023

ด้วย IOption Pattern

ในบทความฉบับนี้ จะอธิบายถึงการอ่านค่า Configuration โดยใช้ standard ที่ Microsoft แนะนำ โดยมีเนื้อหาดังนี้

Configuration

Application Configuration ใน ASP.NET Core นั้นจะถูกจัดการมาจากการอ่าน Configuration Data ที่อยู่ในรูปแบบของ Key-Value Pairs จากหลายๆ Configuration Providers ดังนี้นะครับ.

ในบทความนี้จะขอพูดถึงเฉพาะ Settings Files และ Environment Variables นะครับ ใครสนใจ Provider อื่นก็จิ้มลิ้งที่สนใจข้างบนได้เลยครับผม

IConfiguration

Microsoft ได้เตรียม Interface IConfiguration เพื่อเป็นมาตราฐานในการเป็นศูนย์กลางเพื่อดึงข้อมูลจากหลายๆ Source มาแสดงผลนะครับ

docs.microsoft.com/configuration

ลำดับการดึงข้อมูลมาแสดงเป็น Configuration จะถูกเรียงดังนี้นะครับ (ลำดับที่น้อยกว่าจะถูกเขียนทับด้วยลำดับที่มากกว่านะครับ เช่น เรามี File appsettings.json และมีการ Setup Environment Variables ไว้ ตัวแปร ที่ชื่อเดียวกันจาก appsettings.json จะถูกแทนที่ด้วยตัวแปรจาก Environment Variables นะครับ

  1. appsettings.json
  2. appsettings.{Environment}.json เช่น appsettings.Production.json หรือ appsettings.Development.json นั้นจะอิงการอ่าน File จาก Environment Variable ASPNETCORE_ENVIRONMENT
  3. Environment variables
  4. Command-line arguments
ตัวอย่าง ASPNETCORE_ENVIRONMENT จาก File launchSetting.json ซึ่งเป็นผลให้โปรแกรมทำการอ่าน File appsettings.Development.json ด้วย เพราะมี Environment = Development

Reference ลำดับการดึงข้อมูลนะคับ

จริงๆมีมากกว่านี้นะครับ ใครสนใจสามารถศึกษาเพิ่มเติมได้ที่นี้ครับผม

การดึงข้อมูลจาก appsettings.json

ตัวอย่างการดึงข้อมูลจาก appsettings.json มาใช้งานใน Code จาก docs.microsoft.com/configuration

การดึงข้อมูลจาก Environment Variable

ตัวอย่าง appsettings.json

"Position": {
"Title": "Editor",
"Name": "Joe Smith"
}

สามารถแปลงเป็น Environment Variables ได้ด้วยการใช้ __ มาเป็นตัวคั่นระหว่างชั้นของ Property ได้ดังนี้นะครับ

Windows Cmd

set Position__Title=Windows
set Position__Name=CMD

Bash

export Position__Title="Linux"
export Position__Name="Bash"

เมื่อเรา Setup Environment ตามข้างบนแล้ว ข้อมูลของ Configuration ก็จะถูก Override เมื่อเราสั่ง dotnet run ดังนี้

  • จาก appsettings.json -> Position:Title = “Editor”
  • กลายมาเป็น Environment Variable -> Position__Title = “Windows” ใน Windows
  • กลายมาเป็น Environment Variable -> Position__Title = “Linux” ใน Bash

Configuration — Options pattern

แต่ก่อนเราอาจจะ Hard Code String เพื่อให้สามารถเข้าถึง Configuration Item ได้

ตัวอย่างการดึงข้อมูลจาก appsettings.json มาใช้งานใน Code จาก docs.microsoft.com/configuration
ขอเอาตัวอย่างสมัย web.config มาให้ดูนะครับ จะเห็นว่าเราต้อง Hard Code String เพื่อให้มีชื่อตรงกับ Configuration Item นะครับ

จะดีกว่าไหมถ้าเราสามารถอ้างอิงถึง Configuration Items ได้จาก Strong Type ครับ ซึ่ง Option Pattern ช่วยในเรื่องนี้ได้ครับ และยังช่วยให้เรามั่นใจได้ด้วยว่า Value ของ Configuration ของเราเป็น Type ไหน ไม่ต้องเจอ Error ที่ตอน Runtime จากการ Convert ครับ โดยในบทความนี้เราจะใช้ Pattern นี้ครับ

เราจะเห็นว่าเราแปลงจาก Configuration File ออกมาอยู่ในรูปแบบของ Code C# ซึ่งได้ข้อดีหลักๆคือ มันเป็น Strong Type ชัดเจน การนำไปใช้ต่อก็ทำให้มั่นใจได้ว่าจะไม่เจอ Error จากการ Convert แล้วมีข้อมูลที่ Config ไม่ถูกต้องเกิดขึ้นนะครับ

คุณสมบัติของ Class ที่จะเป็น Option Class

  • ไม่เป็น Abstract Class
  • เปิด Public Read-Write Properties สำหรับ Type จะถูก Bind กับ Configuration Item

ตัวอย่างการนำไปใช้งานนะครับ

ที่ Configure Service เราจะทำการระบุ Class ที่จะใช้ทำ Option Pattern แล้วหลังจากนั้นใน Class ไหนที่อยากจะใช้ Configuration Item เราก็สามารถใช้ Dependency Injection ในการ Inject Option Class เข้าไปที่ Constructure ได้เลยฮะ

ตัวอย่างการใช้ Option Pattern ในบทความนี้

ในหัวข้อถัดๆไปเกี่ยวกับ Infra Project นั้นเราจะทำการสร้าง Option Pattern เพื่อรองรับ Configuration และนำไปเรียกใช้ใน Email Provider นะครับ ส่วน API Project เราจะทำการติดตั้ง Configure นี้ใน appsetting.json และใน program.cs

คำถามที่อาจพบบ่อย (FAQ)

ขออนุญาตแอบแนะนำตัว ผมต้น นคร นะครับ Senior .NET Developer, ทักทายกันได้ที่

https://www.facebook.com/nakorn.rientrakrunchai

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

สำหรับ source code ที่ผมใช้นำเสนอใน FAQ นี้ เพื่อนๆ ดูได้ที่นี่นะคับ

ถ้าไม่อยากใช้ลำดับของ Default Configuration ที่มีอยู่ จะทำใหม่ได้มั้ย

ได้คับ จัดไป, อ้างอิงตามเอกสาร Microsoft กันไปเลย

จากตัวอย่างโค๊ดข้างต้น ตรง configuration.Sources.Clear(); จะเป็นการเครีย Default Configuration แล้ว สร้างใหม่ ให้เอาเฉพาะ Json กันไปเลย โดยจะอ้างอิง ลำดับที่เขียนใน code ด้วยนะคับ อย่างไรก็ตาม ใน .NET 7 จะทำลักษณะ ตามตัวอย่าง นี้ครับ

ถ้าดูตามคอมเม้นสีเขียว ผมจะทำไว้สองแบบ แบบแรก ด้านบน กรอบฟ้า จะเป็นการ เพิ่ม Configuration เข้าไป จากอันเดิมที่มีอยู่ นะครับ,

โดยในการเพิ่มแบบนี้, ทาง Microsoft มีข้อพึงระวัง ดังนี้, ซึ่งมันหมายความว่า Configuration ที่เพิ่มเข้ามา, มันจะไป override ตัวที่มีอยู่แล้ว ถ้าตรงกัน

แบบที่สองคือ ล้าง ทำใหม่เลย คือแบบกรอบส้ม โค๊ดตรง builder.Configuration .Sources.Clear(); จะเป็นการล้างของเดิมออก แล้ว บรรทัดถัดๆมา จะเป็นการใส่เข้าไปใหม่ นะครับ

แล้วใน Console App/Unit test/อื่นๆ นอกจาก web api จะใช้ IConfiguration ได้อย่างไร

สำหรับ Console App, ทาง Microsoft มีคำแนะนำหลายแบบ แต่ผมเลือกแบบนี้ เพราะผมเข้าใจมันได้ง่ายครับ

ซึ่งเมื่อผมลองทำตาม ก็รันผ่านตาม Unit Test, โปรแกรมทำงานได้ปกติ นะคับ

แบบอื่นที่ Microsoft เขียนไว้ คือแบบใช้ hosting, ซึ่งน่าจะเหมาะกับงาน web api หรือ web app มากกว่า, เลยถ้าผมทำ Console App/Unit test/อื่นๆ ผมเลยจะไม่ได้ใช้ท่านี้ครับ

สามารถใช้ Enum มารับค่าจากใน IOption pattern ได้หรือไม่

เพื่อการใช้งานที่ง่าย ผมเลยเกิดคำถามกับตัวเองว่า มันใช้ Enum มารับค่าได้ไหม, จากที่ทดสอบ มันทำได้นะคับ โดยทำตามตัวอย่างนี้

ในกรอบแดง จะเป็นค่าใน appsettings.json, Option class และการใช้ IOption โดย DI ตามลำดับ, สำหรับสีฟ้า คือตัวอย่างการดึงค่า มาใช้ใน program.cs ตรงๆ

ภาพถัดมานี้ จะเป็นการดึงค่ามาใช้ที่ API Controller

ขอขอบคุณป้องกัน ที่สร้างบทความดีๆนี้ขึ้นมา และผมได้ทดลองอ่าน ใช้งาน และผลิต FAQ ขึ้นมา เพื่อเป็นประโยชน์ร่วมกัน, อย่างไรก็ตาม ยังมีอีกหลายบทความที่จะพาให้ทุกคน พัฒนาตัวเองในด้าน .NET ขึ้นมาได้ นะคับ

--

--

Ponggun
T. T. Software Solution

Development Manager, Web Developer with ASP.Net, ASP.net Core, Azure and Microsoft Technologies