Search code examples
c#asp.net-mvchttp-getcustom-model-binder

Custom Model Binder for ASP.NET MVC on GET request


I've created a custom MVC Model Binder which gets called for every HttpPost that comes into the server. But does not get called for HttpGet requests.

  • Should my custom model binder get called during a GET? If so, what did I miss?
  • If not, How can I write custom code handling the QueryString from a GET Request?

Here's my implementation...

public class CustomModelBinder : DefaultModelBinder
{
   public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
   {
      // This only gets called for POST requests. But I need this code for GET requests.
   }
}

Global.asax

protected void Application_Start()
{
   ModelBinders.Binders.DefaultBinder = new CustomModelBinder();
   //...
}

I've looked into these solutions, but they don't quite work for what I'm looking for:

  • Persisting complex types via TempData
  • Using the default binder to build up complex types (?Name=John&Surname=Doe)

Remark on answer

Thanks to @Felipe for the help. Just in case someone struggles with the same, I learnt:

  • The custom model binder CAN be used for GET requests
  • You CAN use DefaultModelBinder class
  • My snag was that the action method MUST have a parameter (otherwise the model binder is skipped for GET Requests, which makes sense when you think about it)

Solution

  • Let's supose you have your own type you want to bind.

    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        // other properties you need
    }
    

    You can create a custom model bind for this specific type, inherithing from DefaultModelBinder, for sample:

    public class PersonModelBinder : DefaultModelBinder
    {
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var request = controllerContext.HttpContext.Request;
    
            int id = Convert.ToInt32(request.QueryString["id"]);
            string name = request.QueryString["name"];
            int age = Convert.ToInt32(request.QueryString["age"]);
            // other properties
    
            return new Person { Id = id, Name = name, Age = age };
        }
    }
    

    In the Global.asax in the Application_Start event, you can registry this model bind, for sample:

    // for Person type, bind with the PersonModelBinder
    ModelBinders.Binders.Add(typeof(Person), new PersonModelBinder());
    

    In the BindModel method from the PersonModelBinder, make sure you have all parameters in the querystring and give them the ideal treatment.

    Since you have this action method:

    public ActionResult Test(Person person)
    {
      // process...
    }
    

    You can access this action with an url something like this:

    Test?id=7&name=Niels&age=25