ismet
ismet

Reputation: 39

ASP.NET Core MVC filtering: How can I send multiple value to action?

I want to filter products in my e-commerce project, but I have a problem: I want my filtering to change dynamically, I choose a brand from the selected list and the necessary filtering is done. When the second filter is done, my first filter is reset and the last filtering becomes valid.

enter image description here

I need such a URL structure:

/?SelectedVendor=Asus&SelectedMemory=4+GB

FilterViewModel.cs

public class FilterViewModel
    {
        public List<string> Vendors { get; set; }
        public List<string> Memories { get; set; }
        public string SelectedVendor { get; set; }
        public string SelectedMemory { get; set; }
    }

CategoryController.cs

    [HttpGet]
    public ViewResult Gaming(int productPage = 1, FilterViewModel model=null)
    {
        
        ProductListViewModel productList = new ProductListViewModel()
        {
            Products =
                _productService.GetProductsByCategoryId(1).OrderBy(p => p.Id).Skip((productPage - 1) * pageSize).Take(pageSize),
            FilterTypes = new FilterViewModel()
            {
                Vendors = _productService.Products.Select(I => I.Vendor).Distinct().OrderBy(I => I).ToList(),
                Memories = _productService.Products.Select(I => I.MemoryCapacity).Distinct().OrderBy(I => I).ToList(),
            }
        };


        if (!string.IsNullOrEmpty(model.SelectedVendor))
        {
            productList.Products = productList.Products.Where(I => I.Vendor.Contains(model.SelectedVendor));
            productList.FilterTypes.Memories = productList.Products.Select(I => I.MemoryCapacity).Distinct()
                .OrderBy(I => I).ToList();
        }

        if (!string.IsNullOrEmpty(model.SelectedMemory))
        {
            productList.Products = productList.Products.Where(I => I.MemoryCapacity == model.SelectedMemory);
        }

        return View(productList);
    }

FilterPartial.cshtml

<div class="col-md-3">
        <div class="filter filter-first">
            <h6 class="font-weight-bold">Brand</h6>

            <form method="get" asp-controller="@controllerName" asp-action="@actionName">

                @foreach (var vendor in Model.Vendors)
                {
                    <div class="mt-2 mb-2 pl-2">
                        <input type="submit" value="@vendor" asp-for="SelectedVendor"/>
                    </div>
                }


                <h6 class="font-weight-bold">Memory</h6>
                @foreach (var memory in Model.Memories)
                {
                    <div class="mt-2 mb-2 pl-2">
                        <input type="submit" asp-for="SelectedMemory" value="@memory"/>
                    </div>
                }
            </form>

        </div>
    </div>

Upvotes: 0

Views: 1842

Answers (2)

Yiyi You
Yiyi You

Reputation: 18189

Here is a demo to pass both SelectedVendor and SelectedMemory to action:

TestFilter.cshtml:

@await Html.PartialAsync("Partial", Model.FilterTypes)
<script>
    function addSelectedVendor(i) {
        $("#SelectedVendor").val($(i).val());
        $("#form1").submit();
    }
    function addSelectedMemory(i) {
        $("#SelectedMemory").val($(i).val());
        $("#form1").submit();
    }
    </script>

Partial.cshtml:

<form id="form1" method="get" asp-controller="Test" asp-action="TestFilter">

    @foreach (var vendor in Model.Vendors)
    {
        <div class="mt-2 mb-2 pl-2">
            <input type="button" value="@vendor" onclick="addSelectedVendor(this)" />
        </div>
    }


    <h6 class="font-weight-bold">Memory</h6>
    @foreach (var memory in Model.Memories)
    {
        <div class="mt-2 mb-2 pl-2">
            <input type="button" value="@memory" onclick="addSelectedMemory(this)" />
        </div>
    }
    <input hidden asp-for="SelectedVendor"/>
    <input hidden asp-for="SelectedMemory"/>
</form>

TestController(I use fake data to test):

 [HttpGet]
            public IActionResult TestFilter(FilterViewModel model)
            {
                ProductListViewModel productList = new ProductListViewModel {  FilterTypes=new FilterViewModel()};
                productList.FilterTypes.Vendors = new List<string> { "Apple", "Asus", "Dell", "Lenovo", "MSI" };
                productList.FilterTypes.Memories = new List<string> { "16GB", "4GB", "8GB"};
    
                return View(productList);
            }

result: enter image description here

Upvotes: 1

hasaneyldrm
hasaneyldrm

Reputation: 87

You can filter by list in your get method.

you should change get method like that

   public virtual IEnumerable<TEntity> Get(
        Expression<Func<TEntity, bool>> filter = null,
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
        string includeProperties = "")
    {
        IQueryable<TEntity> query = DbSet;

        if (filter != null) query = query.Where(filter);

        if (includeProperties != null)
            foreach (var includeProperty in includeProperties.Split
                (new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
                query = query.Include(includeProperty);


        if (orderBy != null)
            return orderBy(query).ToList();
        return query.ToList();
    }

Upvotes: 0

Related Questions