Niels Filter Niels Filter - 2 months ago 8
C# Question

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)


Answer

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