loading...
Cover image for Filter a List in Razor Pages .net core 2.2

Filter a List in Razor Pages .net core 2.2

zoltanhalasz profile image Zoltan Halasz ・3 min read

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:

        <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.

    // 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.

        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

        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
I hope you enjoyed this small reading.
Let me know if you have a better way!

Discussion

pic
Editor guide
Collapse
cgnguyen profile image
Gia Nguyen

It seems that my model binding doesn't work. I've set it to an object property that contains another property. They all have public getters and setters. But the values are null when debugging. I've tried to use the BindProperty attribute on the object as well as the property that has to be accessed. Is there something else I'm forgetting?

Collapse
zoltanhalasz profile image
Zoltan Halasz Author

This has to be within an Asp.net core Razor Pages project (not MVC). And, myBillingCodes, myEmployees, myCateg has to be lists that are populated (from a database for example).

Collapse
pcoganwu profile image
pcoganwu

Please where is the Generated page

Collapse
zoltanhalasz profile image
Zoltan Halasz Author

You have to create a new Asp.Net Core Web Project, add aRazor Page called "Generated". This will contain the three filters and table. The above was just an example, no specific sample project is attached. There is then a table in the context, called "GeneratedDetail" which can be then filtered using linq or foreach as above.

Collapse
pcoganwu profile image
pcoganwu

Thanks Zoltan. You example helped.

Collapse
pcoganwu profile image
pcoganwu

Thanks Zoltan