asp.net-coresearchmultipleselectionmultiple-select-query

Multiple select dropdown menu search string result when selecting more than one entry in the drop down


I have built a drop down menu with names as a filter that is applied to a table of projects. I want to be able to select multiple entries from the drop down and apply them as a filter. A single entry filter works fine, but a multiple select search filter does not return any project records. When nothing is selected in the drop down menu no project is displayed either. How can I amend my search parameter result to show all projects when the search filter is empty and display the projects allocated to the multiple people selected in the drop down menu.

My Project class:

    public class Project
    {
        public int Id { get; set; }

        [Display(Name = "PID")]
        public int PID { get; set; }

        [Display(Name = "Name")]
        public string ProjectName { get; set; }

        [Display(Name = "Client")]
        public int ClientId { get; set; }
        public Client Client { get; set; }

        [Display(Name = "Status")]
        public string ProjectStatus { get; set; }

        [Display(Name = "Forecast Owner")]
        public string ForecastOwner { get; set; }

        [Display(Name = "DSM")]
        public string DSM { get; set; }
        public ICollection<ProjectComment> ProjectComments { get; set; }

My Index.cshtml.cs:

        [BindProperty]
        public List<ClientVM> ClientVMList { get; set; }
        //added for filter - start
        public string CurrentFilter { get; set; }
        //added for filter - end

        //added for filter - string searchString
        public async Task<IActionResult> OnGet(string searchString)
        {
            //added for filter - start
            CurrentFilter = searchString;
            //added for filter - end

                var clientlist = (await _context.Client
                .Include(cc => cc.ClientComments).ToListAsync());
            var projectlist = (await _context.Project
                .Include(pc => pc.ProjectComments)
                //added for filter - start
                .Where(s => s.DSM == (searchString))
                //added for filter - end 
                .ToListAsync());

            ClientVMList = new List<ClientVM>();

            foreach (var item in clientlist)
            {
                ClientVM clientVM = new ClientVM()
                {
                    Projectlist = new List<ProjectVM>(),
                };
                clientVM.ClientName = item.ClientName;
                clientVM.ClientId = item.Id;
                if (item.ClientComments != null && item.ClientComments.Any())
                {
                    clientVM.ClientStatusComment = item.ClientComments.OrderByDescending(cc => cc.LastUpdateDate).First().ClientStatusComment;
                    clientVM.ClientRAG = item.ClientComments.OrderByDescending(cc => cc.LastUpdateDate).First().ClientRAG;
                    clientVM.LastUpdateDate = item.ClientComments.OrderByDescending(cc => cc.LastUpdateDate).First().LastUpdateDate;
                    clientVM.ClientStatusCommentId = item.ClientComments.OrderByDescending(cc => cc.LastUpdateDate).First().Id;
                }
                else
                {
                    clientVM.ClientStatusComment = "No Status Comment";
                }
                foreach (var projectItem in projectlist)
                {
                    ProjectVM projectVM = new ProjectVM
                    {
                        ClientId = projectItem.ClientId,
                        ProjectId = projectItem.Id,
                        ProjectPID = projectItem.PID,
                        ProjectName = projectItem.ProjectName,
                        ProjectStatusName = projectItem.ProjectStatus,
                        ForecastOwnerLongName = projectItem.ForecastOwner,
                        DSMLongName = projectItem.DSM,
                    };
                    if (projectItem.ProjectComments != null && projectItem.ProjectComments.Any())
                    {
                        projectVM.ProjectStatusComment = projectItem.ProjectComments.OrderByDescending(pc => pc.LastUpdateDate).First().ProjectStatusComment;
                        projectVM.RAGStatusName = projectItem.ProjectComments.OrderByDescending(pc => pc.LastUpdateDate).First().ProjectRAG;
                        projectVM.LastUpdateDate = projectItem.ProjectComments.OrderByDescending(pc => pc.LastUpdateDate).First().LastUpdateDate;
                        projectVM.ProjectStatusCommentId = projectItem.ProjectComments.OrderByDescending(pc => pc.LastUpdateDate).First().Id;

                    }
                    else
                    {
                        projectVM.ProjectStatusComment = "No Status Comment";
                    }
                    clientVM.Projectlist.Add(projectVM);
                }
                ClientVMList.Add(clientVM);
            }

            return Page();

The form tag in my Index.cshtml:

<form asp-page="./Index" method="get">
    <div class="dropdown">
            <div class="input-group mb-3">
                <div class="input-group-prepend">
                    <label class="input-group-text" for="inputGroupSelect01">DSM</label>
                </div>
                <select class="custom-select" id="inputGroupSelect01" multiple="multiple" name="SearchString" value="@Model.CurrentFilter">
                    <option selected>Choose a DSM...</option>
                    <option value="Anna">Anna</option>
                    <option value="Bernard">Bernard</option>
                    <option value="Carlo">Carlo</option>
                </select>
            </div>
            <input type="submit" value="Search" class="btn btn-primary" /> |
            <a asp-page="./CommentGroupings/Index">Back to full List</a>
        </p>
    </div>
</form>

The search string result in the URL:

https://localhost:44358/Lists?SearchString=Anna&SearchString=Bernard&SearchString=Carlo

And with one single string selected:

https://localhost:44358/Lists?SearchString=Anna

I want to display all records when there is nothing selected and all records allocated to the people when more than one name is selected. I understand that the issue is related to the way I have set up the search string in the Index.cshtml.cs file, but I have not found a way to amend it in order for my search to fully work.

The lines I am refering to are:

.Where(s => s.DSM == (searchString))
CurrentFilter = searchString;

Any help would be much appreciated.


Solution

  • The search string result in the URL:

    https://localhost:44358/Lists?SearchString=Anna&SearchString=Bernard&SearchString=Carlo

    You need to use List<string> searchString to accept all selected valued with the same name SearchString, and then add your judgments for searchString, for example:

    public async Task<IActionResult> OnGet(List<string> searchString)
        {
    
            CurrentFilter = searchString;
    
            //condition to show all data
            if (searchString.Count == 0 || searchString[0] == "Choose a DSM...")
            {
                var projectlist = await _context.Project.ToListAsync();
            }
            //condition to show filtered data
            else
            {
                var projectlist = await _context.Project
                                  .Include(pc => pc.ProjectComments)                
                                  .Where(s => searchString.Contains(s.DSM))               
                                  .ToListAsync();
            }
            //other logic
    }