简体   繁体   English

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

[英]C# MVC: When to use a specific (non-default) ModelBinder?

It is my understanding that the default model binder is capable of turning 据我了解,默认模型联编程序能够

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

into: 变成:

 [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 } 

In what scenario would I use the non-default model binder? 在哪种情况下,我将使用非默认模型联编程序? I can't think of a reason not to name the HTML input's any differently than class property names. 我想不出一个名称与类属性名称不同的名称。 Please clarify, with an example. 请举例说明。

Thank you! 谢谢!

In the scenario that your MyType for instance doesn't have a default constructor (the default modelbinder needs a default constructor). 在您的MyType例如没有默认构造函数的情况下(默认modelbinder需要默认构造函数)。
This can happen if you use the factory method pattern for creating a new object (very simple example just for illustration ;-): 如果您使用工厂方法模式创建新对象,则可能会发生这种情况(非常简单的示例只是为了说明;-):

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

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

Then you would have to implement a custom modelbinder which calls the factory method CreateNewMyType() instead of creating a new MyType through reflection: 然后,您将必须实现一个自定义模型绑定程序,该模型调用工厂方法CreateNewMyType()而不是通过反射创建新的MyType

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

Also if you're not happy with the current functionality or implementation of the default modelbinder, then you can easily replace it with your own implementation. 另外,如果您对默认Modelbinder的当前功能或实现不满意,则可以轻松地将其替换为自己的实现。

Scott Hanselman has a simple case study for a custom model binder. Scott Hanselman有一个针对自定义模型活页夹的 简单 案例研究。

The point of the post isn't that what he's trying to do can't be done other ways with the default binding, but that he's attempting it allows him to re-use code that will do the job for him. 这篇文章的要点不是用默认绑定无法以其他方式完成他想做的事情,而是 他正在尝试 让他重新使用将为他完成工作的代码。

Consider a custom type called TimeInterval that is stored as a double, but is displayed as hh.mm.ss.ffffff where ffffff is fractional seconds. 考虑一个称为TimeInterval的自定义类型,该类型存储为双精度型,但显示为hh.mm.ss.ffffff ,其中ffffff是小数秒。 With custom binding, it is possible to show the binder how to properly parse and display these numbers, without having to write custom code in the controller. 使用自定义绑定,可以向绑定程序显示如何正确解析和显示这些数字,而不必在控制器中编写自定义代码。

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

Now binding happens automatically for the new custom type. 现在,对于新的自定义类型,绑定会自动发生。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM