Search code examples
c#asp.net-core-mvc

ASP.NET Core filter logic not working - missing details in GET request


I'm working on an ASP.NET Core application, and I'm having trouble getting the filter logic to work as expected. When I submit the filter form, nothing happens, and it appears that the relevant details, such as the OrderID, are missing from the GET request.

Here's an overview of the relevant code:

HTML form:

 <form asp-action="FilterOrders" method="get">
    <div class="form-horizontal">
        <div class="row">
            <div class="form-group col-md-4">
                <label class="control-label">Filter By:</label>
                @Html.DropDownList("filterBy", new SelectList(new List<string>
                {
                "OrderID", "Order Date", "Delivery Date", "Supplier"
                }), "Select Filter", new { @class = "form-control" })
            </div>
            <div class="form-group col-md-4">
                <label class="control-label">Filter Text:</label>
                <input type="text" id="filterText" name="filterText" class="form-control" placeholder="Enter filter text">
            </div>
            <div class="form-group col-md-4 align-self-end">
                <input type="submit" value="Filter" class="btn btn-outline-primary" />
                <a asp-action="Index" class="btn btn-outline-dark">Clear</a>
            </div>
        </div>
    </div>
</form>

Controller action:

 //GET: Orders/Filter/5
//Using LINQ to filter Orders
[HttpGet]
public IActionResult FilterOrders(int OrderID, DateTime? startDate, DateTime? endDate, string Supplier)
{
    var filteredOrders = _ordersService.GetAllOrders();

    if (OrderID != 0)
    {
        filteredOrders = filteredOrders.Where(o => o.OrderID == OrderID);
    }

    if (startDate.HasValue)
    {
        filteredOrders = filteredOrders.Where(o => o.OrderDate >= startDate.Value);
    }

    if (endDate.HasValue)
    {
        filteredOrders = filteredOrders.Where(o => o.OrderDate <= endDate.Value);
    }

    if (!string.IsNullOrWhiteSpace(Supplier))
    {
        filteredOrders = filteredOrders.Where((o) => o.Supplier == Supplier);
    }

    var filteredOrderList = filteredOrders.ToList();

    return View("Index", filteredOrderList);
}

I've checked the form and controller action, but I can't figure out why the OrderID and other details are missing in the GET request when I submit the form.

What could be causing this issue, and how can I ensure that the relevant details are included in the GET request when I submit the filter form?


Solution

  • You have one input with a dropdown to select a filter criterion and one input to input the filter value. These two values are exactly what you will be passed when the form is submitted.

    The software cannot know the internal logic that the meaning of the filterText is based on the selection in the dropdown box. You have to program that logic that does the filtering yourself:

    public IActionResult FilterOrders(string filterBy, string filterText)
    {
        switch (filterBy)
        {
            case "OrderID":
                if(int.TryParse(filterText, out int orderID))
                {
                    filteredOrders = filteredOrders.Where(o => o.OrderID == orderID);
                }
                break;
            case "Order Date":
                if (DateTime.TryParse(filterText, out DateTime orderDate))
                {
                    filteredOrders = filteredOrders.Where(o => o.OrderDate == orderDate);
                }
                break;
            case "Delivery Date":
                if (DateTime.TryParse(filterText, out DateTime deliveryDate))
                {
                    filteredOrders = filteredOrders.Where(o => o.DeliveryDate == deliveryDate);
                }
                break;
            case "Supplier":
                if (!string.IsNullOrWhiteSpace(filterText))
                {
                    filteredOrders = filteredOrders.Where((o) => o.Supplier == filterText);
                }
                break;
        }
    
        var filteredOrderList = filteredOrders.ToList();
    
        return View("Index", filteredOrderList);
    }