MVC 處理請求時,`ControllerActionInvoker.InvokeAction()` 會呼叫 `GetParameterValues()` 為 Action 參數賦值,核心委派給 `IModelBinder.BindModel()`。本文深入原始碼解析三大內建 ModelBinder 選擇邏輯與擴充點。
protected virtual object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
{
Type parameterType = parameterDescriptor.ParameterType;
IModelBinder binder = GetModelBinder(parameterDescriptor);
// ... 建立 ModelBindingContext ...
return binder.BindModel(controllerContext, bindingContext);
}
| Action 參數型別 | 使用的 ModelBinder | 說明 |
|---|---|---|
| FormCollection | FormCollectionModelBinder | 綁定表單集合 |
| HttpPostedFileBase | HttpPostedFileBaseModelBinder | 檔案上傳綁定 |
| 其他 (int, string, bool, 複雜型別) | DefaultModelBinder | 最常用、支援巢狀物件、集合、型別轉換 |
private IModelBinder GetModelBinder(ParameterDescriptor parameterDescriptor)
{
return parameterDescriptor.BindingInfo.Binder ?? Binders.GetBinder(parameterDescriptor.ParameterType);
}
public class JsonNetModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var json = controllerContext.HttpContext.Request.InputStream.ReadAsString();
return JsonConvert.DeserializeObject(json, bindingContext.ModelType);
}
}
// 全域註冊 (Global.asax)
ModelBinders.Binders.Add(typeof(MyComplexModel), new JsonNetModelBinder());
// 或參數標記
public ActionResult Save([ModelBinder(typeof(JsonNetModelBinder))] MyComplexModel model) { ... }
掌握 ModelBinder 機制,能優雅處理 JSON 請求體、自訂日期格式、加密參數解密等進階場景,是 MVC 進階開發必修課。