Reputation: 105
I am really frustrated with this, Because I look so many questions and didn't find my answer. I want to implement a global search in my ASP Net Core project. But I want to implement a search box in Layout page, so that It could be used in every page.
My ASP Net Core project shows directors and movies' information. I built an independent razor page for showing the result of search. I used a property named SearchTerm to get the search term as a query string and then search it in database tables:
//from Search.cshtml.cs
[BindProperty(SupportsGet = true)]
public string SearchTerm { get; set; }
And I implemented a search box in Layout view:
@model MastersOfCinema.Pages.SearchModel
// (I referenced to "SearchModel" and with this I'm only able to open that page. Other pages give the error below.)
<header>
<form method="get" class="SearchBox">
<div class="form-group">
<div class="input-group">
<input type="search" class="form-control" asp-for="SearchTerm" asp-route-searchTerm="SearchTerm" />
<span class="input-group-btn">
<button class="btn btn-default" asp-page="./../Search">
<i class="glyphicon glyphicon-search bg-light"></i>
</button>
</span>
</div>
</div>
</form>
</header>
With the code above, I get this error when I open any page (except the search page which is referenced in layout):
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'MastersOfCinema.Pages.Directors.IndexModel', but this ViewDataDictionary instance requires a model item of type 'MastersOfCinema.Pages.SearchModel'.
The error is related to @model MastersOfCinema.Pages.SearchModel apparently. I don't know what to replace it. If I remove that, I get error from asp-for="SearchTerm". Because it doesn't recognise SearchTerm property.
Error CS1963 An expression tree may not contain a dynamic operation MastersOfCinema
I tried many approaches to implement a global search, including partial view and view components. But this is my first project and I am inexperienced. So please help me. Show me an easy approach.
Thanks for any help and if you need more information just ask.
The search works but as I said I get error when I open other pages. I can only open the seach page.
In case you need to see the whole code of Search.cshtml.cs:
public class SearchModel : PageModel
{
private readonly Context _context;
public SearchModel(Context context)
{
this._context = context;
}
public IEnumerable<Director> Director { get; set; }
public IEnumerable<Movie> Movie { get; set; }
[BindProperty(SupportsGet = true)]
public string SearchTerm { get; set; }
public async Task OnGetAsync(string searchTerm)
{
Director = await _context.Director.ToListAsync();
Movie = await _context.Movie.ToListAsync();
Director = GetDirectorByName(SearchTerm);
Movie = GetMovie(SearchTerm);
SearchTerm = searchTerm;
}
public IEnumerable<Director> GetDirectorByName(string searchString)
{
var query = from r in _context.Director
where r.Name.Contains(searchString) || r.Bio.Contains(searchString) ||
r.Country.Contains(searchString) || string.IsNullOrEmpty(searchString)
orderby r.Name
select r;
if (query.Any()) { searchTermFound = true; }
return query;
}
public IEnumerable<Movie> GetMovie(string searchString)
{
var query = from r in _context.Movie
where r.Title.Contains(searchString) || string.IsNullOrEmpty(searchString)
orderby r.Title
select r;
if (query.Any()) { searchTermFound = true; }
return query;
}
public bool searchTermFound = false;
}
Upvotes: 2
Views: 2086
Reputation: 27803
I want to implement a search box in Layout page, so that It could be used in every page
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'MastersOfCinema.Pages.Directors.IndexModel', but this ViewDataDictionary instance requires a model item of type 'MastersOfCinema.Pages.SearchModel'.
To fix the issue and achieve the requirement, you can try to remove @model MastersOfCinema.Pages.SearchModel
from _Layout.cshtml, then manually set name
and value
attribute of input field, like below.
<form method="get" class="SearchBox">
<div class="form-group">
<div class="input-group">
@*<input type="search" class="form-control" asp-for="SearchTerm" asp-route-searchTerm="SearchTerm" />*@
<input type="search" class="form-control" name="SearchTerm" value="@ViewData["SearchTerm"]" asp-route-searchTerm="SearchTerm" />
<span class="input-group-btn">
<button class="btn btn-default" asp-page="./Search">
<i class="glyphicon glyphicon-search bg-light"></i>Search
</button>
</span>
</div>
</div>
</form>
In Search.cshtml.cs
public async Task OnGetAsync(string searchTerm)
{
//...
ViewData["SearchTerm"] = SearchTerm;
}
Test Result
Upvotes: 1