Filter a List in Razor Pages .net core 2.2
Tags: csharp, dotnet, razor
Published: 2019-11-09 09:41:59

I have a big list, of Invoice Details, and I want a page in Razor Pages that can show all the data, or filter it by 3 fields.
In HTML, I will use select dropdown comboboxes.

The HTML with Razor markup will be:

```html
        <div class="col-12 col-md-4 col-lg-4">
            <form class="" id="FilterForm" method="post" asp-page-handler="FilterGenerated">
                <label asp-for=" SelectedBillingCode"></label>
                <select class="form-control mb-1" asp-for="SelectedBillingCode"
                        asp-items="@Model.BillingCodeList" onchange="this.form.submit()"></select>
                <label asp-for=" SelectedEmployee"></label>
                <select class="form-control mb-1" asp-for="SelectedEmployee"
                        asp-items="@Model.EmployeeList" onchange="this.form.submit()"></select>
                <label asp-for=" SelectedCategory"></label>
                <select class="form-control mb-1" asp-for="SelectedCategory"
                        asp-items="@Model.CategoryList" onchange="this.form.submit()"></select>
            </form>
        </div>
```
In the html markup file, below the above section, will be a table that shows all data from the list GeneratedDetail, using a html table - page can be rendered automatically from the model in razor pages, as a first step, before including the above form.


In the meantime, the page code will contain the definition of the main list which is going to be filtered, the three parameters for filter, and the corresponding selectlists. These are included in the properties list of the Page.
```csharp
    // my main list which is displayed in the Razor Page
        public IList<GeneratedDetail> GeneratedDetail { get;set; }
        // filter variable 
        [BindProperty]
        public string SelectedBillingCode { get; set; }
        public IList<SelectListItem> BillingCodeList { get; set; } = new List<SelectListItem>();
        // filter variable 
        [BindProperty]
        public string SelectedEmployee { get; set; }
        public IList<SelectListItem> EmployeeList { get; set; } = new List<SelectListItem>();
        // filter variable 
        [BindProperty]
        public string SelectedCategory { get; set; }
        public IList<SelectListItem> CategoryList { get; set; } = new List<SelectListItem>();
```

There will be a handling method, present also in the form above as asp-page-handler="FilterGenerated". This will load the page using the above three parameters.
```csharp
        public IActionResult OnPostFilterGenerated()
        {
            return RedirectToPage("Generated", new { billingcode = SelectedBillingCode, hrid = SelectedEmployee, category = SelectedCategory });            
        }
```
The main "Get" function of the page will use the three parameters to load the main list using the where clause in LINQ
```csharp
        public async Task<IActionResult> OnGetAsync(string billingcode = null, string hrid=null, string category = null)
        {
// this is the list which is going to be displayed
            GeneratedDetail = new List<GeneratedDetail>();
// include an All Value for the three select form controls            
            BillingCodeList.Add(new SelectListItem() { Text = "All", Value = "All" });
            EmployeeList.Add(new SelectListItem() { Text = "All", Value = "All" });
            CategoryList.Add(new SelectListItem() { Text = "All", Value = "All" });
/// below I load the filter data (billing code, employee list, and category list) in my select controls. The lists of myBillingCodes, myEmployees, myCateg are loaded from tables using EF Core. For the simplicity of this tutorial these are omitted.

            foreach (var bc in myBillingCodes)
                {
                    BillingCodeList.Add(new SelectListItem() { Text = bc.BillingCode.ToString(), Value = bc.BillingCode.ToString() });
                }

            foreach (var emp in myEmployees)
                {
                    EmployeeList.Add(new SelectListItem() { Text = emp.Lastname + " " + emp.Firstname, Value = emp.Hrid.ToString()}); ;
                }

            foreach (var categ in myCateg)
                {
                    CategoryList.Add(new SelectListItem() { Text = categ.CostCategory, Value = categ.CostCategory }); ;
                }
/// filtering the main list using EF core and Where clause
GeneratedDetail = await _context.GeneratedDetail.Where(x => x.BillingCode == billingcode && x.HrId == Int32.Parse(hrid) && x.CostCategory.Contains(category)).ToListAsync();
// load the page

            return Page();
}
```
All three filters can be seen and the change will trigger the submission of the form and show only the filtered part of the big list.
And the result will be, after loading the page:
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/au7gf3ybyhco2lfvlw41.png)
I hope you enjoyed this small reading.
Let me know if you have a better way!