Custom model binder not called when type is nullable
Asked Answered
T

2

7

I have a custom struct called TimeOfDay which is used in a view model like this:

public class MyViewModel
{
  public TimeOfDay TimeOfDay { get; set; }
}

I have created a custom model binder called TimeOfDayModelBinder and registered it in Global.asax.cs like this:

ModelBinders.Binders.Add(typeof(TimeOfDay), new TimeOfDayModelBinder());

And everything works great. However, if I change my view model to this:

public class MyViewModel
{
  public TimeOfDay? TimeOfDay { get; set; } // Now nullable!
}

My custom model binder is no longer called. I know that the property is no longer a type of TimeOfDay, but a Nullable which is different. So does this mean I should add my custom model binder twice in Global.asax.cs like this:

ModelBinders.Binders.Add(typeof(TimeOfDay), new TimeOfDayModelBinder());
ModelBinders.Binders.Add(typeof(TimeOfDay?), new TimeOfDayModelBinder());

It works, but there's just something I don't like about it. Is this really necessary to handle my type as nullable, or is there something I'm missing?

Tatting answered 3/4, 2011 at 23:20 Comment(4)
I don't think you're missing anything. As far as I'm aware that's the standard way of doing it.Phantasy
Did you ever figure this out? I am having a kinda-similar (but not quite) issue. See my question.Scrawny
@notJim I didn't really dig into any more, but the conclusion was that I needed to add the modelbinder twice. Once for the not-nullable and once for the nullable, as it's really two different types to the CLR.Leveret
By the way @LukeH, if you make an answer with your comment, I'll accept it as the answer. :-)Leveret
T
1

Per @LukeH's comment, it seems it is necessary. I guess that makes sense too, as TimeOfDay and Nullable<TimeOfDay> really is two different types in the CLR. So I guess I have to live with it. :-)

Tatting answered 19/4, 2011 at 22:57 Comment(0)
S
8

This isn't really an answer to your question, but an alternative solution. There might be a better one...

In MVC3 you can create a IModelBinderProvider. An implementation would be something like this:

public class TimeOfDayModelBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(Type modelType)
    {
          if(modelType == typeof(TimeOfDay) || modelType == typeof(TimeOfDay?))
            {
                 return  new TimeOfDayModelBinder();
            } 
           return null;
    }
}

You'd need to register it in your DependencyResolver/IOC container or do this (in the Global.asax - app start):

ModelBinderProviders.BinderProviders.Add(new TimeOfDayModelBinderProvider());
Suki answered 3/4, 2011 at 23:31 Comment(1)
+1 Interesting and nice to know. But in my case I think it would complicate matters more than it would simplify it. But thank you anyway. :-)Leveret
T
1

Per @LukeH's comment, it seems it is necessary. I guess that makes sense too, as TimeOfDay and Nullable<TimeOfDay> really is two different types in the CLR. So I guess I have to live with it. :-)

Tatting answered 19/4, 2011 at 22:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.