I am trying to find a good way to implement product filtering in my ASP.NET MVC application.
When a user selects a checkbox value, I want to send a key/value pair (or some other type of collection) to my controller where I can then lookup products in my DB that have the filter (like screen size) and value (say 50") and return that list.
Can someone please recommend a good approach for this? I would like to do this by passing URL parameters so our marketing folks can link to pre-filtered product listing pages.
I've been researching how to pass an object or collection through the URL but haven't had luck implementing it.
Here is a small example of what I'm trying to accomplish:
Pass key "size" and value "50" to MVC controller
public ActionResult subcategory(string brand, string cat, string cat2, Dictionary<string, string> filters)
Return list of products that have screen size of 50", and have checkbox for "Screen Size - 50" checked in View.
Note that new products and associated filters (and their categories) will be added in the future. Ideally, the query string will consist of name/value pairs consisting of the category ID and the selected ID, for example
products/brand/NEC/Pro-Displays/LCD-Monitors?234=43&343=21
where 234
is the ID for the 'Screen Size' category and 43
is the ID for the '50"' monitor, and 343
is for the 'Brightness' category and 21
is the ID '450 Nit'
For reference, here is how I am rendering the checkbox filters in my View:
@for (int x = 0; x < Model.Count(); x++)
{
<div class="filter-cat" data-target="#list-@x">@Model.ElementAt(x).getName() <i class="fa fa-angle-down"></i></div>
<ul id="list-@x">
@for (int y = 0; y < Model.ElementAt(x).getFilterList().Count; y++)
{
<li>
<input type="checkbox" id="@Model.ElementAt(x).getFilterList().ElementAt(y).getDescription()" name="@Model.ElementAt(x).getFilterList().ElementAt(y).getDescription()" />
<label for="@Model.ElementAt(x).getFilterList().ElementAt(y).getDescription()">@Model.ElementAt(x).getFilterList().ElementAt(y).getDescription()</label>
</li>
}
</ul>
}
In order to bind back to your Dictionary<string, string> filters
parameter, you will need to generate inputs in the format
<input type="checkbox" name="filters[xxx]" value="yyy" />
where xxx
is the ID of the filter category, and yyy
is the ID of the selected filter.
Note that since your submitting only the ID values (typeof int
), then your parameter can be Dictionary<string, int> filters
(the Key
still needs to be string
).
But since you have checkboxes meaning that a user can make multiple selections in a category (and dictionary keys must be unique), you will need a (say) suffix in the name
attribute to make them unique.
The code in your view is ugly and difficult to read, debug and unit test, so I recommend you start with a view model(s) to represent what you want to display in the view
public class ProductFilterVM
{
public string Name { get; set; }
... // other properties relating to a product that you may want to display the view - e.g. Description
public IEnumerable<FilterCategoryVM> FilterCategories { get; set; }
}
public class FilterCategoryVM
{
public int ID { get; set; }
public string Name { get; set; }
public List<FilterSelectionVM> Selections { get; set; }
}
public class FilterSelectionVM
{
public int ID { get; set; }
public string Name { get; set; }
}
and in your GET method, initialize an instance of ProductVM
and populate it based on the product being displayed, and return that to the view. The view then becomes
@model ProductFilterVM
....
<h2>@Model.Name</h2>
...
<h3>Filters</h3>
@using (Html.BeginForm("subcategory", "yourControllerName", FormMethod.Get))
{
foreach(var category in Model.FilterCategories)
{
int counter = 1; // used to generate unique keys
<h4>@category.Name</h4>
foreach (var selection in category.Selections)
{
string name = String.Format("filters[{0}-{1}]", category.ID, counter++);
<label>
<input type="checkbox" name="@name" value="@selection.ID" />
<span>@selection.Name</span>
</label>
}
}
<input type="submit" />
}
When you submit, the checked checkboxes will be bound to your filters
parameter, and you will need to parse the Key
back to an int after removing the suffix
public ActionResult subcategory(string brand, ..., Dictionary<string, string> filters)
{
foreach(KeyValuePair<string, int> item in filters)
{
int category = Convert.ToInt32(item.Key.Split('-')[0]);
int filter = item.Value;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.