我的理解是默认模型装订器能够转动
<input type="text" name="myType.property1" value="John Doe" />
<input type="text" name="myType.property2" value="22" />
<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输入命名为类属性名称的原因。请举例说明。
谢谢!
答案 0 :(得分: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();
}
}
此外,如果您对默认模型绑定器的当前功能或实现不满意,那么您可以轻松地将其替换为您自己的实现。
答案 1 :(得分:2)
Scott Hanselman有a simple case study for a custom model binder.
帖子的重点并不在于他试图做的事情不能用默认绑定做其他方式,但是他正在尝试它允许他重用代码为他做好工作。
答案 2 :(得分:2)
考虑一个名为TimeInterval的自定义类型,它存储为double,但显示为 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());
}
现在,新的自定义类型会自动绑定。