ASP.NET MVC Beta 引入自動模型繫結,DefaultModelBinder 取代 Preview 5 手寫 IModelBinder 的繁瑣。本文深入原始碼分析 ControllerActionInvoker 如何調用繫結管線、BindAttribute 如何控制繫結行為、ModelBinderContext 如何封裝繫結上下文。
protected virtual object GetParameterValue(ControllerContext context, ParameterDescriptor parameter)
{
IModelBinder binder = GetModelBinder(parameter); // 取得繫結器
ModelBinderContext bindingContext = new ModelBinderContext
{
ModelName = parameter.ParameterName,
ModelType = parameter.ParameterType,
ValueProvider = context.Controller.ValueProvider,
PropertyFilter = GetPropertyFilter(parameter) // 來自 BindAttribute
};
BinderResult result = binder.BindModel(context, bindingContext);
return result.Model;
}
| 類別/介面 | 職責 |
|---|---|
| BindAttribute | 修飾 Action 參數,控制 Include/Exclude/Prefix、IsPropertyAllowed 謂詞 |
| DefaultModelBinder | 預設繫結實作,遞迴處理複雜類型屬性 |
| ModelBinderContext | 封裝繫結所需:ModelName、ModelType、ValueProvider、PropertyFilter |
| BinderResult | 封裝繫結結果:Model、IsModelSet |
| IValueProvider | 抽象值來源(Form、QueryString、RouteData),統一繫結介面 |
public class BindAttribute : Attribute
{
public string Include { get; set; } // 允許繫結屬性(逗號分隔)
public string Exclude { get; set; } // 排除屬性
public string Prefix { get; set; } // 表單欄位前綴
public bool IsPropertyAllowed(string propertyName) // 判斷屬性是否可繫結
}
用法:
public ActionResult Create([Bind(Include="Name,Price")] Product product) { ... }
ValueProvider 取值轉型BindPropertyPrefix[0].Property 繫結每個元素PropertyFilter(來自 BindAttribute.IsPropertyAllowed)決定是否繫結public class CustomBinder : IModelBinder
{
public object BindModel(ControllerContext context, ModelBindingContext bindingContext)
{
// 自訂繫結邏輯
}
}
// 註冊
ModelBinders.Binders.Add(typeof(MyType), new CustomBinder());