I am creating a recipe blog website. While creating post, I have option to categorize them into Veg and NonVeg posts using an Enum
dropdown. The posts are displayed as cards on index page. I want to create a dropdown filter on index page to display only the selected category.
Enum:
public enum PostCategory
{
[Display(Name = "Veg")]
Veg = 0,
[Display(Name = "NonVeg")]
NonVeg = 1
}
Model:
public class Post
{
// Post
[Key]
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string? Link { get; set; }
public string? Ingredient { get; set; }
public string Recipe { get; set; }
public string Image { get; set; }
// Category
public PostCategory PostCategory { get; set; }
}
Controller:
// Index
[HttpGet]
public async Task<IActionResult> Index()
{
IEnumerable<Post> posts = await _postInterface.GetAll();
return View(posts);
}
// Search Bar
[HttpPost]
public async Task<IActionResult> Index(string searchString, PostCategory postCategory)
{
var posts = from p in _context.Posts select p;
if (!string.IsNullOrEmpty(searchString))
{
posts = posts.Where(t => t.Title!.Contains(searchString));
}
return View(await posts.ToListAsync());
}
// Category Filter goes here.
View:
<!-- Filter -->
<div class="row justify-content-between">
<!-- Search bar -->
<div class="col-4">
<form class="d-flex mb-2" role="search" asp-controller="Post" asp-action="Index">
<input class="form-control me-2" type="search" placeholder="Search Posts" aria-label="Search" name="SearchString" required oninvalid="this.setCustomValidity(' ')" />
<button class="btn btn-outline-success me-2" type="submit">Search</button>
<a class="btn btn-outline-danger" asp-area="" asp-controller="Post" asp-action="Index">Reset</a>
</form>
</div>
<!-- Dropdown -->
<div class="col-4">
<form asp-controller="Post" asp-action="Index" id="category">
<select class="form-control" asp-items="@Html.GetEnumSelectList<PostCategory>()" id="post-filter">
<option value="">All</option>
</select>
<button class="btn btn-outline-success me-2" type="submit">Search</button>
<a class="btn btn-outline-danger" asp-area="" asp-controller="Post" asp-action="Index">Reset</a>
</form>
</div>
</div>
<!-- Cards -->
<div class="album py-5 bg-light">
<div class="container">
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3" id="post-recipe">
@foreach (var item in Model)
{
<div class="col mb-4">
<div class="card shadow-sm">
<img class="bd-placeholder-img card-img-top" src="@item.Image" width="157" height="236" alt="Card image cap">
@* Card Details *@
<div class="card-body">
<a asp-controller="Post" asp-action="Detail" asp-route-id="@item.Id" class="stretched-link"></a>
<h6 class="card-text"> @item.Title </h6>
<div class="d-flex justify-content-between align-items-center">
<small class="text-body-secondary">@item.PostCategory</small>
</div>
</div>
@* Admin privlages *@
<div class="card-footer btn-group">
<a asp-controller="Post" asp-action="Edit" asp-route-id="@item.Id" type="button" class="btn btn-sm btn-outline-primary stretched-link">Edit</a>
<a asp-controller="Post" asp-action="Delete" asp-route-id="@item.Id" type="button" class="btn btn-sm btn-outline-danger stretched-link">Delete</a>
</div>
</div>
</div>
}
</div>
</div>
</div>
I have tried using adding additional [HttpPost]
action in Index for it to only crash route with searchbar action. Combining it with searchbar action helps, as there is no Route crash, but even then, the code is only half complete, not giving the expected results, only showing veg category.
Here is what I have tried:
// Enum Category
[HttpPost]
public IActionResult Index(PostCategory postCategory)
{
var posts = _context.Posts.Where(c => c.PostCategory == postCategory).ToList();
return View(posts);
}
Thank you!
2
Answers
This is the final code I have got that works.
You failed model-binding and PostCategory enum has the default value 0(Veg)
Add the name property to your dropdownlist for model-binding,
also,modify your controller,add the codes for when you select all :
Result: