Binding คือกระบวนการตั้งค่า Values ให้ Parameters เมื่อ Web API เรียก Controller Action Method
Web API Methods มี Parameter Types ต่างๆ และวิธี Customize Binding Process:
- ถ้า Parameter เป็น Simple Type (int, bool, double, ฯลฯ) Web API พยายาม Get Value จาก URI (Route Data หรือ Query String)
- ถ้า Parameter เป็น Complex Type (Customer, Employee, ฯลฯ) Web API Framework พยายาม Get Value จาก Request Body
- เราสามารถเปลี่ยน Default Behavior ได้ด้วย Attributes
[FromBody]และ[FromUri]
FromUri (Default สำหรับ Simple Types)
ถ้า Parameter เป็น Simple Type Web API พยายาม Get Value จาก URI
.NET Primitive Types: int, bool, double, DateTime, Guid, string, และ Type ใดๆ ที่ Convert จาก String ได้
// GET /api/student/123 → id = 123 (จาก Route Data)
// GET /api/student?id=123 → id = 123 (จาก Query String)
public Student Get(int id) { ... }
// GET /api/student?name=John&age=25
public Student Get(string name, int age) { ... }
FromBody (Default สำหรับ Complex Types)
ถ้า Parameter เป็น Complex Type Web API จะ Bind จาก Message Body (ใช้ MediaTypeFormatter)
// POST /api/student Body: { "Id": 1, "Name": "John" }
public Student Post(Student student) { ... }
// PUT /api/student/1 Body: { "Name": "Jane" }
public HttpResponseMessage Put(int id, Student student) { ... }
[FromUri] - บังคับ Bind Complex Type จาก URI
// GET /api/student?Id=1&Name=John
public Student Get([FromUri] Student student) { ... }
// Query String สำหรับ Complex Object
// ?student.Id=1&student.Name=John&student.Address.City=Bangkok
public HttpResponseMessage Get([FromUri] Student student) { ... }
[FromBody] - บังคับ Bind Simple Type จาก Request Body
// POST /api/student Body: "John" (raw string, Content-Type: text/plain)
public Student Post([FromBody] string name) { ... }
// POST /api/student Body: 25 (raw number)
public HttpResponseMessage Post([FromBody] int age) { ... }
ข้อจำกัดสำคัญ: ห้ามมี [FromBody] หลายตัวใน Action เดียว
// ❌ ผิด - มี FromBody 2 ตัว
public Student Post([FromBody] string name, [FromBody] int age) { ... }
// ✅ ถูก - ใช้ Complex Type แทน
public class StudentDto {
public string Name { get; set; }
public int Age { get; set; }
}
public Student Post([FromBody] StudentDto dto) { ... }
Parameter Binding Rules Summary
| Parameter Type | Default Source | Force URI | Force Body |
|---|---|---|---|
| Simple (int, string, bool, DateTime, Guid, etc.) | URI (Route/Query) | Auto | [FromBody] |
| Complex (Class, Array, List, etc.) | Request Body | [FromUri] | Auto |
| IFormFile / HttpPostedFileBase | Request Body (Multipart) | N/A | Auto |
| CancellationToken | Auto-injected | N/A | N/A |
Custom Parameter Binding (Advanced)
// Custom Model Binder
public class CommaSeparatedIntArrayBinder : IModelBinder {
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) {
var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (value == null) return false;
var ids = value.AttemptedValue.Split(',')
.Select(s => int.TryParse(s, out var i) ? i : (int?)null)
.Where(i => i.HasValue)
.Select(i => i.Value)
.ToArray();
bindingContext.Model = ids;
return true;
}
}
// Usage
public IEnumerable Get([ModelBinder(typeof(CommaSeparatedIntArrayBinder))] int[] ids) { ... }
// GET /api/student?ids=1,2,3,4,5
ใน ASP.NET Core
[FromQuery]- แทน[FromUri](Query String เท่านั้น)[FromRoute]- Route Data เท่านั้น[FromBody]- Request Body (JSON/XML/Form)[FromHeader]- Request Headers[FromForm]- Form Data (application/x-www-form-urlencoded)[FromServices]- Dependency Injection