Filter/Search using Multiple Fields - ASP.NET MVC
I recommend you separate concerns and use an approach that the code in your controller be like this, simple, beautiful and extensible:
public ActionResult Index(ProductSearchModel searchModel)
{
var business = new ProductBusinessLogic();
var model = business.GetProducts(searchModel);
return View(model);
}
Benefits:
- You can put anything you need in your
ProductSearchModel
based on your requirements. - You can write any logic in
GetProducts
based on requirements. There is no limitation. - If you add a new field or option to search, your action and controller will remain untouched.
- If the logic of your search changes, your action and controller will remain untouched.
- You can reuse logic of search wherever you need to search on products, in controllers or even in other business logic.
- Having such
ProductSearchModel
, you can use it as model ofProductSearch
partial view and you can applyDataAnnotations
to it to enhance the model validation and help UI to render it usingDisplay
or other attributes. - You can add other business logic related to your product in that business logic class.
- Following this way you can have a more organized application.
Sample Implementation:
Suppose you have a Product
class:
public class Product
{
public int Id { get; set; }
public int Price { get; set; }
public string Name { get; set; }
}
You can create a ProductSearchModel
class and put some fields you want to search based on them:
public class ProductSearchModel
{
public int? Id { get; set; }
public int? PriceFrom { get; set; }
public int? PriceTo { get; set; }
public string Name { get; set; }
}
Then you can put your search logic in ProductBusinessLogic
class this way:
public class ProductBusinessLogic
{
private YourDbContext Context;
public ProductBusinessLogic()
{
Context = new YourDbContext();
}
public IQueryable<Product> GetProducts(ProductSearchModel searchModel)
{
var result = Context.Products.AsQueryable();
if (searchModel != null)
{
if (searchModel.Id.HasValue)
result = result.Where(x => x.Id == searchModel.Id);
if (!string.IsNullOrEmpty(searchModel.Name))
result = result.Where(x => x.Name.Contains(searchModel.Name));
if (searchModel.PriceFrom.HasValue)
result = result.Where(x => x.Price >= searchModel.PriceFrom);
if (searchModel.PriceTo.HasValue)
result = result.Where(x => x.Price <= searchModel.PriceTo);
}
return result;
}
}
Then in your ProductController
you can use this way:
public ActionResult Index(ProductSearchModel searchModel)
{
var business = new ProductBusinessLogic();
var model = business.GetProducts(searchModel);
return View(model);
}
Important Note:
In a real world implementation, please consider implementing a suitable Dispose
pattern for your business class to dispose db context when needed. For more information take a look at Implementing a Dispose method or Dispose Pattern.
Searching Multiple Fields in ASP.net MVC: Passing parameters from view to controller
According to your comment, i want to share solution for your problem. Of course you can change get or post method depends on you, but you are right about being get method. Filtering methods are generally http get. There are two approach for get filtered value from view to controller:
One way;
[HttpGet]
public ActionResult Index(DonationView viewModel)
{
DonationSearchModel search= viewModel.DonationSearchModel;
//You can reach your search model over donationview
return View();
//return View(await donations.ToListAsync());
}
Second way;
[HttpGet]
public ActionResult Index([Bind(Prefix = "DonationSearchModel")]DonationSearchModel donationSearchModel)
{
DonationSearchModel search= donationSearchModel;
//You can reach your search model over donationSearchModel
return View();
//return View(await donations.ToListAsync());
}
How do I make a filtered search with multiple fields
First, change your view to use textboxes rather than radio buttons.
@model IEnumerable<MvcApplication7.Models.vwtest21>
<p>
@using (Html.BeginForm("Index", "Home", FormMethod.Get))
{
<b>Search By:</b>
@Html.TextBox("progcd") <text>PROGCD</text>
@Html.TextBox("docrecdt") <text>DOCRECDT</text>
<input type="submit" value="Search" />
}
</p>
Then change your controller to filter by the new textboxes.
public class HomeController : Controller
{
private ProjectDBContext db = new ProjectDBContext();
public ActionResult Index(string progcd, string docrecdt)
{
return View(db.vwtest21.Where(x => x.DOC_REC_DT1 == docrecdt && x.PROG_CD == progcd).ToList());
}
}
The AND condition (&&) means that only records that meet both search filters will be returned. You may wish to change it to an OR condition (||) if you want to return records that meet either search condition.
How do i filter and search selected fields only and exclude null textboxes in ASP.NET MVC
Assuming you are using EntityFramework and LazyLoading is disabled and your entities have navigation properties Lab_Sample_Status
and Patient
, you can utilize the IQueryable
like the ff:
int custId = (int)Session["UserCustid"];
// eager load navigation properties
// query is IQueryable
var query = db.Lab_Orders.Include("Lab_Sample_Status").Include("Patient").Where(r => r.CUSTID == custId);
if (startdate.HasValue && enddate.HasValue)
{
query = query.Where(r => DbFunctions.TruncateTime(r.Lab_Sample_Status.CollectionDate) >= DbFunctions.TruncateTime(startdate.Value) &&
DbFunctions.TruncateTime(r.Lab_Sample_Status.CollectionDate) <= DbFunctions.TruncateTime(enddate.Value));
}
if (!string.IsNullOrEmpty(pcfileno))
{
query = query.Where(r => r.Lab_Sample_Status.PcFileNo == pcfileno);
}
if (!string.IsNullOrEmpty(idno))
{
query = query.Where(r => r.Patient.PatientNo == idno);
}
// .. You can continue to manipulate the query
// db results is determined upon calling ToList()
var model = query.ToList().Select(r => new Orders_Tables() { LabOrders = r, LabOrderStatus = r.Lab_Sample_Status, Patient = r.Patient });
return View(model);
If you don't have navigation properties like indicated above, you can do the ff:
int custId = (int)Session["UserCustid"];
// query is IQueryable
var query = db.Lab_Orders.Where(r => r.CUSTID == custId)
.Join(db.Lab_Sample_Status, order => order.order_status, status => status.status_id, (order, status) => new { Order = order, Status = status })
.Join(db.Patients, rec => rec.Order.patient_no, patient => patient.Patient_No, (rec, patient) => new Orders_Tables { LabOrders = rec.Order, LabOrderStatus = rec.Status, patients = patient });
if (startdate.HasValue && enddate.HasValue)
{
query = query.Where(r => DbFunctions.TruncateTime(r.LabOrderStatus.CollectionDate) >= DbFunctions.TruncateTime(startdate.Value) &&
DbFunctions.TruncateTime(r.LabOrderStatus.CollectionDate) <= DbFunctions.TruncateTime(enddate.Value));
}
if (!string.IsNullOrEmpty(pcfileno))
{
query = query.Where(r => r.LabOrderStatus.PcFileNo == pcfileno);
}
if (!string.IsNullOrEmpty(idno))
{
query = query.Where(r => r.patients.Patient_No == idno);
}
// db results is determined upon calling ToList()
var model = query.ToList();
return View(model);
PS: I'm hesitant to post this as an answer since OP's question isn't clear enough but the comment section has gotten a bit long.
MVC 5 Search multiple columns
Your current code is doing filtering on the ClipName
property first and assigning the result to SearchResult
variable. Then in the second line you are doing the filter on the ClipKeywords
property on the same result (SearchResult
, which is the filtered result from the previous line). So effectively you are doing an AND here.
You can do OR in your where clause.
if (!String.IsNullOrEmpty(searchString))
{
SearchResult = SearchResult
.Where(s => s.ClipName.Contains(searchString)
||s.ClipKeywords.Contains(searchString));
}
Filtering search using multiple dropdowns in MVC gives null Model
You need to make sure the Model
property of the search model is not null and has been passed to the action, then when searching you need to make sure Model
property of the element in linq query is not null, then compare MakeID
property of the search model with MakeID
property of the element in linq query. For example if you are going to search based on MakeID
of the Model
, if it's been specified, then you need to change the code to the following:
if (searchModel.Model !=null && searchModel.Model.MakeID.HasValue)
result = result.Where(x => x.Model !=null &&
x.Model.MakeID == searchModel.Model.MakeID);
However if you are following this post, in general it's better to follow these advises:
- Do not use your Entity model as your POCO search model.
- Do not put business logic in your POCO class.
- If you are going to search based on MakeID, include it directly in the POCO search model.
Example
I'll extend the example from linked post, so the Product
have a Category
property as well and we are interested to search based on CategoryName
as well as some other properties:
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Product
{
public int Id { get; set; }
public int Price { get; set; }
public string Name { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
}
You can create a ProductSearchModel
class and put some fields you want to search based on them:
public class ProductSearchModel
{
public int? Id { get; set; }
public int? PriceFrom { get; set; }
public int? PriceTo { get; set; }
public string Name { get; set; }
public string CategoryName { get; set; }
}
Then you can put your search logic in ProductBusinessLogic
class this way:
public class ProductBusinessLogic
{
private YourDbContext Context;
public ProductBusinessLogic()
{
Context = new YourDbContext();
}
public IQueryable<Product> GetProducts(ProductSearchModel searchModel)
{
var result = Context.Products.AsQueryable();
if (searchModel != null)
{
if (searchModel.Id.HasValue)
result = result.Where(x => x.Id == searchModel.Id);
if (!string.IsNullOrEmpty(searchModel.Name))
result = result.Where(x => x.Name.Contains(searchModel.Name));
if (searchModel.PriceFrom.HasValue)
result = result.Where(x => x.Price >= searchModel.PriceFrom);
if (searchModel.PriceTo.HasValue)
result = result.Where(x => x.Price <= searchModel.PriceTo);
if (!string.IsNullOrEmpty(searchModel.CategoryName))
result = result.Where(x => x.Category !=null &&
x.Category.Name.Contains(searchModel.Name));
}
return result;
}
}
Related Topics
How to Catch a Specific SQLexception Error
Most Efficient Way to Insert Rows into MySQL Database
Post Form Data Using Httpwebrequest
Wpf Binding a Listbox to an Enum, Displaying the Description Attribute
How to Restart a Wpf Application
C# Console Receive Input with Pipe
"Could Not Load Type [Namespace].Global" Causing Me Grief
Hashtable with Multidimensional Key in C#
"Updatesourcetrigger=Propertychanged" Equivalent for a Windows Phone 7 Textbox
Question Mark and Colon in Statement. What Does It Mean
How to Bring My Application Window to the Front
When Using Trusted_Connection=True and SQL Server Authentication, Will This Affect Performance
Value Cannot Be Null. Parameter Name: Source
"The Given Path's Format Is Not Supported."
Inject Service into Action Filter