Click here to Skip to main content
15,889,844 members
Articles / Web Development / HTML

Implementing Search Without Convoluted If Statements In ASP.NET MVC

Rate me:
Please Sign up or sign in to vote.
4.67/5 (5 votes)
15 Feb 2016CPOL2 min read 11.7K   5   8
Implementing search without convoluted If statements in ASP.NET MVC

Implementing Search Without Convoluted If Statements In Asp.Net MVC

Introduction

In the beginning, when I start to learn C# and ASP.NET MVC, building search form was a complicated thing to do for me, the more criteria I've had for a search form, the harder it would get, but it was hard because I didn't use the proper tools to do my job, back then, I didn't know about IQueryable interface and what Linq deferred execution was. In this post, I'm going to show you how you can build any kind of search form without complicating things, using Linq deferred execution.

Search Form, The Wrong Way

First, I'm going to show you the wrong way to do it, and I'm telling you, if your search becomes more than a mere two field, the logic can become a real mess, Imagine we have a search form like this:

Image 1

And here our ugly, naive, mess of code for this form:

JavaScript
public ActionResult ManageOrders
(DateTime fromDate, DateTime toDate, string tracingCode, string customerName)
        {
            if (!string.IsNullOrEmpty(fromDate) && !string.IsNullOrEmpty(toDate) 
            && string.IsNullOrEmpty(tracingCode) && string.IsNullOrEmpty(customerName))
            {
                var model = db.Orders.Where(s => s.OrderDate >= fromDate && s.OrderDate <= toDate);
                return View(model);
            }
            else if (!string.IsNullOrEmpty(fromDate) && !string.IsNullOrEmpty(toDate) 
            && !string.IsNullOrEmpty(tracingCode) && !string.IsNullOrEmpty(customerName))
            {
                var model = db.Orders.Where(s => s.OrderDate >= fromDate 
                && s.OrderDate <= toDate 
                && s.TracingCode == tracingCode && s.CustomerName == customerName);
                return View(model);
            }
            else if (!string.IsNullOrEmpty(fromDate) && !string.IsNullOrEmpty(toDate) 
            && string.IsNullOrEmpty(tracingCode) && !string.IsNullOrEmpty(customerName))
            {
                var model = db.Orders.Where(s => s.OrderDate >= fromDate 
                && s.OrderDate <= toDate && s.CustomerName == customerName);
                return View(model);
            }
            else if (!string.IsNullOrEmpty(fromDate) && !string.IsNullOrEmpty(toDate) 
            && !string.IsNullOrEmpty(tracingCode) && string.IsNullOrEmpty(customerName))
            {
                var model = db.Orders.Where(s => s.OrderDate >= fromDate 
                && s.OrderDate <= toDate && s.TracingCode == tracingCode);
                return View(model);
            }
            else if (string.IsNullOrEmpty(fromDate) && string.IsNullOrEmpty(toDate) 
            && !string.IsNullOrEmpty(tracingCode) && !string.IsNullOrEmpty(customerName))
            {
                var model = db.Orders.Where(s => s.TracingCode == tracingCode 
                && s.CustomerName == customerName);
                return View(model);
            }
            else if (string.IsNullOrEmpty(fromDate) && string.IsNullOrEmpty(toDate) 
            && string.IsNullOrEmpty(tracingCode) && !string.IsNullOrEmpty(customerName))
            {
                var model = db.Orders.Where(s => s.CustomerName == customerName);
                return View(model);
            }
            else if (string.IsNullOrEmpty(fromDate) && string.IsNullOrEmpty(toDate) 
            && !string.IsNullOrEmpty(tracingCode) && string.IsNullOrEmpty(customerName))
            {
                var model = db.Orders.Where(s => s.TracingCode == tracingCode);
                return View(model);
            }

            return View(db.Orders);            
	    }

As you can see, we have to check for each and every one of the conditions, for when one field is filled and others are empty and vise versa, and return the correct filtered model, this approach is just plain wrong and shouldn't be used, at least when we have Linq and deferred execution.

Search From, The Right Way

With the powers that Linq and its deferred execution give us, we turn the above code to this:

JavaScript
public ActionResult ManageOrders
(DateTime fromDate, DateTime toDate, string tracingCode, string customerName)
        {
            IQueryable<orders> orders = db.Orders;

            if (!string.IsNullOrEmpty(fromDate) && !string.IsNullOrEmpty(toDate))
            {
                orders = orders.Where(s => s.OrderDate >= startDate && s.OrderDate <= endDate);
            }

            if (!string.IsNullOrEmpty(tracingCode))
            {
                orders = orders.Where(s => s.TracingCode.Contains(tracingCode));
            }

            if (!string.IsNullOrEmpty(customerName))
            {
                orders = orders.Where(s => s.CustomerName.Contains(customerName));
            }
			
            return View(orders);
	    }</orders>

You can make it even shorter if you use ternary if, but the point is, now all we had to do was to check if the action parameter is not empty, and add another where to our search query. Here, we use Linq to SQL which is different form Linq to object, but we can use Linq to object too, which means we can use IEnumerable instead of IQueryable, but using IQueryable here is more efficient, here is a good explanation of their difference, to put it briefly, Linq to SQL runs our query in the SQL Server, so we get only what we need, but Linq to object retrieves the whole entity and then filters it in memory.

With deferred execution that Linq gives us, we can build an IQueryable or IEnumerable and accumulate our wheres on it based on our conditions, this is far better than what we had before.

This article was originally posted at http://www.hamidmosalla.com/feeds/posts/default

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Iran (Islamic Republic of) Iran (Islamic Republic of)
Programming is my passion, because I find it so intellectually rewarding. I currently work as a back-end web developer, using Microsoft technology stack, I also blog about my experiences and contribute to open source projects on my free time.

Comments and Discussions

 
QuestionAbout Post Pin
Member 1174823822-Feb-16 20:58
Member 1174823822-Feb-16 20:58 
QuestionQuerying for many filters Pin
Member 1039877316-Feb-16 22:42
Member 1039877316-Feb-16 22:42 
AnswerRe: Querying for many filters Pin
Hamid Mosalla17-Feb-16 0:59
Hamid Mosalla17-Feb-16 0:59 
QuestionHow well does this scale for large datasets? Pin
ahagel16-Feb-16 10:38
professionalahagel16-Feb-16 10:38 
AnswerRe: How well does this scale for large datasets? Pin
Hamid Mosalla17-Feb-16 1:18
Hamid Mosalla17-Feb-16 1:18 
GeneralRe: How well does this scale for large datasets? Pin
ahagel17-Feb-16 4:13
professionalahagel17-Feb-16 4:13 
GeneralMy vote of 4 Pin
Santhakumar M15-Feb-16 21:09
professionalSanthakumar M15-Feb-16 21:09 
GeneralMy Vote of 5 Pin
aarif moh shaikh15-Feb-16 17:25
professionalaarif moh shaikh15-Feb-16 17:25 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.