public interface IModelBinder
{
object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext);
}
單一方法,輸入 Controller 上下文與繫結上下文,回傳繫結結果物件。
ParameterDescriptor 的 BindingInfo 屬性(ParameterBindingInfo)含 Binder 屬性,優先用於該參數繫結。
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Class | ...)]
public abstract class CustomModelBinderAttribute : Attribute
{
public abstract IModelBinder GetBinder();
}
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Class | ...)]
public sealed class ModelBinderAttribute : CustomModelBinderAttribute
{
public ModelBinderAttribute(Type binderType);
public override IModelBinder GetBinder() => (IModelBinder)Activator.CreateInstance(BinderType);
public Type BinderType { get; }
}
ParameterDescriptor 只掃描參數本身的屬性,忽略參數型別(類別/介面/結構)上的 ModelBinderAttribute。
public class FooModelBinder : IModelBinder { ... }
public class BarModelBinder : IModelBinder { ... }
public class Foo { }
[ModelBinder(typeof(BarModelBinder))] // 型別上標註
public class Bar { }
public class Baz { }
public class HomeController : Controller
{
public void Index()
{
var controllerDesc = new ReflectedControllerDescriptor(typeof(HomeController));
var actionDesc = controllerDesc.FindAction(ControllerContext, "DoSomething");
var fooBinder = actionDesc.GetParameters().First(p => p.ParameterName == "foo").BindingInfo.Binder;
var barBinder = actionDesc.GetParameters().First(p => p.ParameterName == "bar").BindingInfo.Binder;
var bazBinder = actionDesc.GetParameters().First(p => p.ParameterName == "baz").BindingInfo.Binder;
Response.Write($"foo: {fooBinder?.GetType().Name ?? "N/A"}<br/>");
Response.Write($"bar: {barBinder?.GetType().Name ?? "N/A"}<br/>");
Response.Write($"baz: {bazBinder?.GetType().Name ?? "N/A"}<br/>");
}
public void DoSomething([ModelBinder(typeof(FooModelBinder))] Foo foo, Bar bar, Baz baz) { }
}
輸出:
foo: FooModelBinder
bar: N/A
baz: N/A
結論: 僅參數上的 [ModelBinder(typeof(FooModelBinder))] 生效;型別 Bar 上的屬性被忽略。
[ModelBinder(typeof(CustomBinder))] T param。ModelBinders.Binders.Add(typeof(T), new CustomBinder())(於 Global.asax)。IModelBinderProvider (MVC 5+) 或自訂 ModelBinderProvider。IModelBinder 為繫結核心介面,ModelBinderAttribute 提供參數層級宣告式指定,但不支援型別層級屬性。全域註冊需用 ModelBinders.Binders。理解此機制可精準控制每個參數的繫結策略。