C#MVC:何时使用特定的(非默认)ModelBinder?

时间:2009-06-10 19:49:22

标签: c# asp.net-mvc

我的理解是默认模型装订器能够转动

<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输入命名为类属性名称的原因。请举例说明。

谢谢!

3 个答案:

答案 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());
}

现在,新的自定义类型会自动绑定。