2009-06-10 28 views
1

這是我的理解是默認的模型粘合劑能夠轉動C#MVC:何時使用特定(非默認)ModelBinder?

<input type="text" name="myType.property1" value="John Doe" /> 
<input type="text" name="myType.property2" value="22" /> 

成:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult SomeAction(MyType myType) 
{ 
    // This will be "John Doe" 
    String someName = myType.property1; 
    // This will be 22 
    Int32 someNumber = myType.property2; 


    // 
    // irrelevant magic 
}   

在什麼情況下我會使用非默認的模型綁定?我不能想到一個理由,不要命名HTML輸入與類屬性名稱不同。請舉例說明。

謝謝!

回答

3

在例如您的MyType沒有默認構造函數(默認模型綁定器需要默認構造函數)的情況下。
如果使用工廠方法模式創建一個新的對象(很簡單的例子,只是爲了說明;-)這可能發生:

public class MyType 
{ 
    private MyType() // prevent direct creation through default constructor 
    { 
    } 

    public static MyType CreateNewMyType() 
    { 
     return new MyType(); 
    } 
} 

那麼你就必須實現它調用工廠方法的自定義模型綁定器CreateNewMyType()而不是創建一個新的MyType通過反思:

public class MyTypeBinder : DefaultModelBinder 
{ 
    protected override object CreateModel(ControllerContext controllerContext, 
              ModelBindingContext bindingContext, 
              Type modelType) 
    { 
     return MyType.CreateNewMyType(); 
    } 
} 

此外,如果你不滿意目前的功能或實現的默認模型綁定器,那麼你可以很容易地用自己的實現來替代它。

+0

你可以添加一個自定義modelbinder實現的例子嗎? – Alex 2009-06-10 20:14:21

+0

Alex,我在一個單獨的答案中添加了一個自定義的模型綁定器實現。 – 2009-06-10 20:20:53

2

考慮一個名爲TimeInterval的自定義類型,該類型存儲爲雙精度型,但顯示爲hh.mm.ss.ffffff其中ffffff是小數秒。通過自定義綁定,可以顯示活頁夾如何正確解析並顯示這些數字,而無需在控制器中編寫自定義代碼。

// This class implements a custom data type for data binding. 
public class TimeInterval 
{ 
    double _value; 

    public TimeInterval(string value) 
    { 
     // Extension method parses string value to double. 
     _value = value.ToSeconds(); 
    } 
    public TimeInterval(double value) 
    { 
     _value = value; 
    } 
    public string GetText() 
    { 
     // Extension method formats double value as time string. 
     return _value.ToTimeString(); 
    } 
    public double? GetValue() 
    { 
     return _value; 
    } 
} 

// This class implements custom binding for the TimeInterval custom type. 
// It is registered in Global.asax 
public class TimeIntervalBinder : IModelBinder 
{ 
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     string value = GetAttemptedValue(bindingContext); 

     if (value == "") 
      return null; 

     return new TimeInterval(value); 
    } 

    private static string GetAttemptedValue(ModelBindingContext context) 
    { 
     ValueProviderResult value = context.ValueProvider[context.ModelName]; 
     return value.AttemptedValue ?? string.Empty; 
    } 
} 

// in Global.asax: 
protected void Application_Start() 
{ 
    RegisterRoutes(RouteTable.Routes); 
    ModelBinders.Binders.Add(typeof(TimeInterval), new TimeIntervalBinder()); 
} 

現在爲新的自定義類型自動綁定。