+2  A: 

In the scenario that your MyType for instance doesn't have a default constructor (the default modelbinder needs a default constructor).
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:

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.

fretje
Could you add an example for custom modelbinder implementation?
Alex
Alex, I added a custom modelbinder implementation in a separate answer.
Robert Harvey
Thank you Robert !!!
Alex
Here you go, now you also have an example which implements a custom modelbinder by overriding DefaultModelBinder instead of implementing IModelBinder ;-)
fretje
+2  A: 

Scott Hanselman has a simple case study for a custom model binder.

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.

mannish
Definitely a case study, but hardly simple. He really wrapped himself around the axle on this one.
Robert Harvey
point taken... ;)
mannish
+1  A: 

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. 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.

Robert Harvey