首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> 關於ASP.NET

ASP.NET MVC ModelBinder 核心機制:IModelBinder、CustomModelBinderAttribute 與 ModelBinderAttribute

     編輯:關於ASP.NET

IModelBinder 介面

public interface IModelBinder
{
    object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext);
}

單一方法,輸入 Controller 上下文與繫結上下文,回傳繫結結果物件。

ModelBinder 選擇機制:ParameterDescriptor.BindingInfo.Binder

ParameterDescriptor 的 BindingInfo 屬性(ParameterBindingInfo)含 Binder 屬性,優先用於該參數繫結。

CustomModelBinderAttribute 抽象基類

[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Class | ...)]
public abstract class CustomModelBinderAttribute : Attribute
{
    public abstract IModelBinder GetBinder();
}

ModelBinderAttribute:內建具體實作

[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。理解此機制可精準控制每個參數的繫結策略。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved