MVC搜索功能实现:基于SearchParameters ViewModel的搜索表单开发问询
Alright, let's walk through finishing this MVC search feature step by step—you’ve already got the SearchParameters ViewModel and a start on the search form, which is a solid foundation. Here’s how to tie it all together:
First, you’ll need two action methods in your controller: one to serve the empty search form, and another to process the submitted search criteria. Here’s an example using a repository pattern (adjust based on your data access setup):
public class RecordsController : Controller { private readonly IRecordRepository _recordRepo; // Inject your repository via constructor (dependency injection) public RecordsController(IRecordRepository recordRepo) { _recordRepo = recordRepo; } // GET: Show empty search form public IActionResult Search() { // Pass an empty SearchParameters model to the view return View(new SearchParameters()); } // POST: Handle search form submission [HttpPost] public IActionResult Search(SearchParameters searchParams) { // Validate user input first if (!ModelState.IsValid) { // If validation fails, send the form back with error messages return View(searchParams); } // Fetch matching records from your data layer var searchResults = _recordRepo.GetMatchingRecords(searchParams); // Pass results to a dedicated results view return View("SearchResults", searchResults); } }
Make sure your form is correctly bound to the SearchParameters ViewModel using Tag Helpers, and includes validation feedback. Here’s how to structure it:
@model SearchParameters <h2>Search Records</h2> <form asp-action="Search" method="post"> <div class="mb-3"> <label asp-for="FirstName" class="form-label"></label> <input asp-for="FirstName" class="form-control" /> <span asp-validation-for="FirstName" class="text-danger"></span> </div> <div class="mb-3"> <label asp-for="LastName" class="form-label"></label> <input asp-for="LastName" class="form-control" /> <span asp-validation-for="LastName" class="text-danger"></span> </div> <div class="mb-3"> <label asp-for="AltName" class="form-label"></label> <input asp-for="AltName" class="form-control" /> <span asp-validation-for="AltName" class="text-danger"></span> </div> <div class="mb-3"> <label asp-for="DateOfRecord" class="form-label"></label> <input asp-for="DateOfRecord" class="form-control" type="date" /> <span asp-validation-for="DateOfRecord" class="text-danger"></span> </div> <button type="submit" class="btn btn-primary">Run Search</button> </form>
The asp-for Tag Helper automatically pulls the DisplayName from your ViewModel, and asp-validation-for will show any validation errors (like invalid date formats).
This is where you’ll filter your data based on the user’s input. If you’re using Entity Framework Core, here’s a sample repository method:
public class RecordRepository : IRecordRepository { private readonly AppDbContext _dbContext; public RecordRepository(AppDbContext dbContext) { _dbContext = dbContext; } public IEnumerable<Record> GetMatchingRecords(SearchParameters searchParams) { var query = _dbContext.Records.AsQueryable(); // Filter by First Name if provided (case-insensitive fuzzy search) if (!string.IsNullOrWhiteSpace(searchParams.FirstName)) { query = query.Where(r => r.FirstName.Contains(searchParams.FirstName, StringComparison.OrdinalIgnoreCase)); } // Filter by Last Name if (!string.IsNullOrWhiteSpace(searchParams.LastName)) { query = query.Where(r => r.LastName.Contains(searchParams.LastName, StringComparison.OrdinalIgnoreCase)); } // Filter by Alternate Name if (!string.IsNullOrWhiteSpace(searchParams.AltName)) { query = query.Where(r => r.AltName.Contains(searchParams.AltName, StringComparison.OrdinalIgnoreCase)); } // Filter by Date of Record (match the date only, ignore time) if (searchParams.DateOfRecord.HasValue) { var targetDate = searchParams.DateOfRecord.Value.Date; query = query.Where(r => r.DateOfRecord.Date == targetDate); } return query.ToList(); } }
Adjust the filtering logic based on your needs: use == for exact matches instead of Contains if that’s what you want, or add date range filters if users should search between two dates.
Make a new view (e.g., SearchResults.cshtml) to display the results. Here’s a basic example:
@model IEnumerable<Record> <h2>Search Results</h2> @if (!Model.Any()) { <div class="alert alert-info"> No records found matching your search criteria. </div> } else { <table class="table table-striped"> <thead> <tr> <th>First Name</th> <th>Last Name</th> <th>Alternate Name</th> <th>Date of Record</th> </tr> </thead> <tbody> @foreach (var record in Model) { <tr> <td>@record.FirstName</td> <td>@record.LastName</td> <td>@record.AltName</td> <td>@record.DateOfRecord.ToString("yyyy-MM-dd")</td> </tr> } </tbody> </table> } <p><a asp-action="Search" class="btn btn-link">Back to Search Form</a></p>
- Add Pagination: If your search could return hundreds of records, implement pagination to keep the UI responsive.
- Persistent Search Criteria: Pass the original
SearchParametersto the results view so users can tweak their query without retyping everything. - Async Support: Update your controller and repository to use async methods (e.g.,
ToListAsync()instead ofToList()) for better scalability. - Advanced Validation: Add data annotations to your
SearchParametersViewModel (like[MaxLength(50)]) to enforce input limits.
内容的提问来源于stack exchange,提问作者rajaha

