มาสร้าง Restful Api ด้วย .Net Core กันเถอะ

Waranchit Chaiwong
4 min readNov 19, 2021

--

Introduction

สวัสดีทุกคนที่เข้ามาด้วยนะครับ (หรืออาจจะหลงเข้ามาก็เป็นได้…). ช่วงนี้เป็นช่วงที่ผมกำลังศึกษาเกี่ยวกับ การสร้าง Simple API ของฝั่ง Backend โดยใช้ .Net Core, Entity framework, และ Postgres. วันนี้เลยอยากจะมาแชร์เกี่ยวกับขั้นตอนการทำ รวมทั้ง แหล่งเรียนรู้เพิ่มเติมหากใครสนใจ.

Web API

Initial Project

ก่อนอื่นเราจะมาสร้าง Initial Project ประเภท Web API ของเราก่อนนะฮะ ในบทความนี้ผมจะใช้ IDE ที่ชื่อว่า Rider ในการ development

  1. เริ่มต้นให้เรา New Project ขึ้นมาก่อน
  2. Tab ด้านซ้าย ให้เลือก ASP.NET core Web Application
  3. ในส่วนของ Solution name และ Project name สามารถใส่ได้ตามต้องการเลย
  4. หากเราต้องการ initial git ด้วย ก็ติ๊กถูกที่ช่อง Create Git repository ได้เลย มันจะ init ให้เราตั้งแต่เริ่ม project เลย
  5. SDK ก็เลือกตามที่จะใช้เลย ในครั้งนี้ผมใช้ .Net 5 (หากใครสงสัยว่า .Net 5 คืออะไร เดี๋ยวผมจะทิ้งลิ้งไว้ท้ายบทความให้ไปอ่านเพิ่มละกันครับ)
  6. Type ส่วนนี้สำคัญครับ มันเป็นเหมือนการเลือกเราจะสร้างโปรเจคในลักษณะงานแบบไหน ในบทความนี้ให้เราเลือก Web API
  7. หากไม่มีการ set อะไรเพิ่มเติม ก็กดปุ่ม Create ได้เลย

Create Controller

ในส่วนนี้เราจะมาสร้าง controller กันนะครับ โดยส่วนนี้ผมมองว่าจะเป็นเหมือนด่านหน้า เมื่อมี Request จาก Client(ในที่นี้อาจจะเป็น Frontend หรือ Mobile application or etc.) เข้ามาที่ API service เรา ก็จะเจอ Controller ก่อน. โดยเราจะเลือกสร้างจาก dotnet command, สร้าง Class เองแล้วใส่รายละเอียดที่ต้องใช้ หรือ ในบทความนี้เราจะใช้ Rider เราก็สามารถ สร้าง Template ของ Web API ขึ้นมาได้ง่ายๆเลย.

  1. ให้คลิกขวาที่โฟรเดอร์ Controllers จากนั้นคลิกที่ New Scaffolded Item…

2. ใส่ชื่อ Controller และ เลือก Template ที่ต้องการ ในบทความนี้เราจะเลือกใช้ API Controller — Empty

ข้อ 1: เราจะเรียกสิ่งที่เป็น […] ว่า Attribute.

ในภาพ [Route(“api/[controller]”)] หมายความว่าเรากำหนดให้ Controller จะจัดการกับ request ที่เข้ามาด้วย endpoint /api/[controller].

[controller] เป็นการที่ตัว dotnet จะหยิบเอาชื่อของ class Controller มาใส่โดยจะตัดคำว่า Controller ออก. ในตัวอย่าง [controller] คือ Todolist. ดังนั้น ถ้ามี request ที่เข้ามาด้วย endpoint api/Todolist ก็จะเข้า Class นี้.

แต่ในที่นี้เราสามารถกำหนดเองได้ตามต้องการ

Attribute ที่น่าสนใจนอกจาก Route

  • สำหรับ Define HttpMethod
  • สำหรับ Binding source ที่มาจาก Request เข้า model หรือ object บางอย่าง เช่น RequestBody, Query string parameter, RequestHeader

Controller 101

หลังจากก่อนหน้านี้เราสร้าง Class Controller. ในส่วนนี้เราจะมาสร้าง method เพื่อ จัดการ request แต่ละ method ที่เข้ามา.

Line 30 และ 37: จะเห็นได้ว่าเรามีการใช้ Attribute [FromBody] เพื่อ binding request body กับ Model ที่เรากำหนด ในที่นี้คือ CreateOrUpdatetodoListDto.

การสร้าง method เพื่อจัดการ request ก็เหมือนการสร้าง method ใน class ทั่วไปเลย โดย Action Return Type ของ Web API method จะแบ่งออกเป็น 3 ประเภท

  • Specific type
  • IActionResult
  • ActionResult<T>

Specific type

หากต้องการ Return ของแค่ Type เดียว เราสามารถใช้ Action Return Type ประเภทนี้ได้ โดย Return type ก็จะเหมือนการประกาศ method ใน class ทั่วไปเลย. โดย Return Type จะเป็น Primitive type หรือ Complex type ก็ได้.

IActionResult

ใช้ในกรณีที่ต้องการ Return ของ หลาย ๆ Type(Type ในที่นี้หมายถึง Object Result จะมีอะไรบ้างนั้น เดี๋ยวผมแปะลิงค์ไว้ใต้โพส).

ActionResult<T>

Action return type ประเภทนี้จะมีความหลายกับ IActionResult แต่ต่างตรงที่ ActionResult<T> สามารถ Return ได้ระหว่าง Object Result และ Specific type.

EF Core x Postgres

หลังจากที่ก่อนหน้านี้เรา implement ในส่วน Controller กันไปแล้ว. ต่อมาเราจะมา implement ส่วนของ Repository. โดยในบทความนี้เราจะใช้ EF หรือชื่อเต็มๆคือ Entity Framework ซึ่งเป็น ORM ของฝั่ง .NET ที่นิยมมาก

โดยในส่วนนี้ผมจะมาเล่าว่า ต้องติดตั้ง Lib ตัวไหนบ้าง โดยที่เราต้องติดตั้งจะประกอบไปด้วย

  • Microsoft.EntityFrameworkCore 5.0.12
  • Npgsql.EntityFrameworkCore.PostgreSQL 5.0.10
  • Microsoft.EntityFrameworkCore.Design 5.0.12

อย่าลืมลง Postgres กันด้วยนะฮะ จะลงในเรื่องเลยหรือจะลงใน container ก็ตามที่สะดวกเลยฮะ.

Data Model

ในส่วนนี้เราจะมาสร้าง data model กันก่อน โดย data model ก็คือ class นึงที่จะมี properties หลายๆอัน ให้นึกภาพว่า class คือ Table และ properties ก็คือ column แต่ละอัน.

  • Line 3: ปกติแล้วหากเราไม่กำหนด Attribute ให้กับ Data class model ในตอน migration ชื่อ table ของเราคือชื่อ Class ที่ไม่มีคำว่า Model. แต่หากต้องการกำหนดชื่อ table เองก็สามารถกำหนด Attribute ตาม line ที่ 3 ได้เลย

ตัวอย่างหากไม่กำหนด Attribute: TodolistModel => Todolist(ชื่อ Table)

  • Line 5: property ตัวนี้เปรียบเสมือน Primary key โดย
  • [Column(…)] เป็น Attribute ตัวหนึ่ง ใช้เพื่อกำหนดคุณสมบัติของ column นั้นๆ เช่น กำหนด ชื่อ, data type ซึ่งหากเราไม่กำหนดชื่อให้มัน มันจะหยิบเอาชื่อ Property ไปเป็นชื่อ Column.

DbContext

ในส่วนนี้เราจะมาประกาศ สิ่งที่เรียกว่า DbContext. มันคือ class ที่เราจะเอาไว้ mapping ระหว่าง Data Model กับ Table ใน Database.

Connection String

ในส่วนนี้เราจะมากำหนด ConnectionString ที่ใช้เชื่อมต่อกับ Database ที่เราจะใช้ โดยในบทความนี้เราจะใช้ Postgres นะฮะ ถ้าใครใช้ตัวอื่นแล้วอยากดูตัวอย่างการกำหนดรูปแบบของ ConnectionString เดี๋ยวผมจะแปะลิงค์ไว้ใต้บทความ.

Register DbContext

ในส่วนนี้เราจะ register ตัว DbContext เข้ากับ App Startup เพื่อที่ว่า หากมี Class ไหนก็ตามที่ Require dependency DbContext มันก็จะ Inject เข้า Class นั้นๆให้อัตโนมัติ ถ้าผมจำไม่ผิด มันจะเรียกกระบวนการนี้ว่า IoC(inversion of control)

Line 8: คือการ get connection string จาก config

Migration

  • Initial Migration With dotnet

dotnet ef migrations add InitialCreate

หากขึ้นข้อความแบบนี้ แสดงว่า initial migration เสร็จแล้ว.

  • Create Table schema from migration(ที่เราทำไปขั้นตอนก่อนหน้า)

dotnet ef datebase update

หากขึ้นแบบนี้ แสดงว่า เรา migrate table ลงใน Database เรียบร้อยละ ทีนี้เราก็พร้อมจะใช้งานจริงๆละ ขั้นต่อไปเราจะเริ่มimplement ในส่วนของ repository กัน

EF Core x Postgres In Action

ในส่วนนี้เราจะเริ่ม implement repository กันนะครับ โดยในบทความนี้เราจะใช้ Repository pattern เข้ามาช่วย. Repository pattern คือการที่เราสร้าง Abstraction Layer ขึ้นมาระหว่าง ส่วนของ Business logic และ ส่วนของ Data Access layer ในมุมมองของผมที่ได้ลองกับตัวเอง ผมมองว่าวิธีนี้ทำให้เรา เขียน unit test ง่ายขึ้น

จากรูปคือการนำเอา repository pattern มาใช้. หากเราต้องการเขียน unit test เราก็แค่ mocking ตัว repository ก็คือจบละ ไม่ต้องไปยุ่งกับ Data Access layer (ในที่นี้คือ DbContext) หากใครสนใจรายละเอียดเพิ่มเติมเกี่ยวกับ Repository pattern เดี๋ยวผมแปะลิงค์ไว้ใต้บทความนะครับ

Implementing Repository

  • Define abstraction layer
  • Implementing

--

--