ASP.NET MVC ModelBinder: Use ModelBinders For QueryStrings

ModelBinding is popular for sending form data back to the server, but did you know that you can use ModelBinders with GETS as well as POSTS? This quick tip will show you how to pass QueryString parameters to the server using a Model.

October 31st, 2014 • MVC •
0 (0 votes)
ModelBinding with QueryStrings

ModelBinders were introduced as a way to send your data from the page over to the server. When you post your data back to the server from a form, your POST method in your controller can use either a ViewModel or a FormCollection parameter.

But did you know that when you access a page using a GET instead of a POST, you can pass QueryStrings, cookies, or any other Request parameters into a Model and use them in your pages.

Let's go to our old friend the FaqController from our past post.

Paging Mr. FAQ

Let's have our FaqController Index page accept paging parameters.

We need to make our paging model so we'll create the following class:

Models\PagingModel.cs

namespace ModelBindingExample.Models
{
    public class PagingModel
    {
        public int PageIndex { get; set; }
        public int PageSize { get; set; }
    }
}

Now we need to tell MVC that our model attaches to a ModelBinder class. Makes sense, right? :-)

For each model you want to bind, you need the ModelBinderAttribute to point your model to your ModelBinder class as shown below.

using System.Web.Mvc;
using ModelBindingExample.ModelBinders;
namespace ModelBindingExample.Models
{
    [ModelBinder(typeof(PagingBinder))]
    public class PagingModel
    {
        public int PageIndex { get; set; }
        public int PageSize { get; set; }
    }
}

Now let's work on our PagingBinder ModelBinder class. You can either inherit from the DefaultModelBinder class or use the IModelBinder with the BindModel method.

When you use the DefaultModelBinder method, you need to override the BindModel method.

ModelBinder\PagingBinder.cs

using System.Web.Mvc;
using ModelBindingExample.Models;
namespace ModelBindingExample.ModelBinders
{
    public class PagingBinder: DefaultModelBinder
    {
        public override object BindModel(ControllerContext controllerContext,
            ModelBindingContext bindingContext)
        {
            var request = controllerContext.HttpContext.Request;

            var index = request.QueryString.Get("Page");             var size = request.QueryString.Get("Size");
            int pageIndex;             if (!int.TryParse(index, out pageIndex))                 pageIndex = 0; // Default Page
            int pageSize;             if (!int.TryParse(size, out pageSize))                 pageSize = 20; // Default 20 FAQs

            return new PagingModel             {                 PageIndex = pageIndex,                 PageSize = pageSize             };         }     } }

See near the top of the method where we use QueryString? We can easily replace that with any type of data in the Request object. We could use Cookies, Form Data, UserAgent, IPAddresses, or even Referral Urls. Whatever we want to grab, we can store in a model.

Now that we have our modelbinder, we can use the model in our FaqController Index page.

Controllers\FaqController.cs

// GET: FAQ
public ActionResult Index(PagingModel model)
{
    return View(_factory.GetViewModel<FaqController, FaqViewModel>(this));
}

It's all set up as a parameter in our Index page/method. When we run it for the first time using the following URL:

http://localhost:4985

we see our model will have the default values: Page = 0 and Size = 20.

Paging Model with Default Values

But when we use the following URL

http://localhost:4985?Page=2&Size=10

we see the values passed from the QueryString.

Paging Model with QueryString Values

Conclusion

The ModelBinders are perfect for gathering specific data from HTTP Requests and passing them into your controllers in a neat, tidy little package instead of having HttpContext.Currents all over the place. When you receive this nice model in your controllers, it's kind of like Christmas!

Ok, maybe not Christmas, but it makes your code a lot cleaner and testable in the long run.

I hope this tip helps you out.

UPDATE: By request, I added a quick unit test for this Model Binder with a post called Unit Testing ASP.NET MVC Model Binders.

Was this informative? Share it!

Looking to become a better developer?

Sign up to receive ReSharper Design Pattern Smart Templates, ASP.NET MVC Guidelines Checklist, and Newsletter Updates!

Picture of Jonathan Danylko

Jonathan Danylko is a freelance web architect and avid programmer who has been programming for over 20 years. He has developed various systems in numerous industries including e-commerce, biotechnology, real estate, health, insurance, and utility companies.

When asked what he likes to do in his spare time, he replies, "Programming."

comments powered by Disqus