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.

Written by Jonathan "JD" Danylko • Last Updated: • MVC •
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.

ASP.NET 8 Best Practices on Amazon

ASP.NET 8 Best Practices by Jonathan Danylko


Reviewed as a "comprehensive guide" and a "roadmap to excellence" with over 120 Best Practices for ASP.NET Core 8, Jonathan's first book by Packt Publishing explores proven techniques for every phase of the SDLC.

Learn industry-standard concepts to improve your coding, debugging, and deployment of ASP.NET Core websites.

Order now on Amazon.com button

Picture of Jonathan "JD" Danylko

Jonathan "JD" Danylko is an author, web architect, and entrepreneur who's been programming for over 30 years. He's developed websites for small, medium, and Fortune 500 companies since 1996.

He currently works at Insight Enterprises as an Architect.

When asked what he likes to do in his spare time, he replies, "I like to write and I like to code. I also like to write about code."

comments powered by Disqus