I have a small ASP.NET Core Razor Pages project. I'm making a simple list display page with a basic search functionality. In my model, I have 4 page handlers (2 of them are added for debug purposes):
public async Task OnGetAsync()
{
Posting = await _context.Postings
.Include(p => p.ItemDetails).Include(p => p.Owner).ToListAsync();
}
public async Task OnPostAsync()
{
Posting = await _context.Postings
.Include(p => p.ItemDetails).Include(p => p.Owner).ToListAsync();
}
public async Task<PageResult> OnGetSearchAsync(String search)
{
if (String.IsNullOrEmpty(search))
{
search = search.Trim();
Posting = await _context.Postings.Where(p => p.ItemDetails.ItemName.Contains(search)).ToListAsync();
}
return Page();
}
public async Task<PageResult> OnPostSearchAsync(String search)
{
if (!String.IsNullOrEmpty(search))
{
search = search.Trim();
Posting = await _context.Postings
.Where(p => p.ItemDetails.ItemName.Contains(search)).ToListAsync();
}
return Page();
}
When the form specifies method="post"
with asp-page-handler="search"
, the form calls the correct handler (OnPostSearchAsync(String search)
). However, when the form specifies method="get"
with asp-page-handler="search"
, the form calls the wrong handler (OnGetAsync()
). Is this intended? If so how can i call a custom handler while using the GET
method? Maybe using a custom handler isn't necessary but i think i should be able to if i choose to.
Here is the relevant code in .cshtml
file:
<div id="posting_search_bar_container">
<form method="get" asp-page-handler="search">
<input type="text" name="search" />
<input type="submit" value="Ara" />
</form>
</div>
<div id="posting_list_container">
@if (Model.Posting != null)
{
@foreach (var posting in Model.Posting)
{
<partial name="./Partials/_Posting" model="new Pages.Postings.Partials.PostingModel(posting);" />
}
}
</div>
In terms of why this happens, this answer should explain what's going on here. Essentially, asp-page-handler
sets up an action URL that includes ?handler=search
, which then gets trashed by the browser for GET requests.
In terms of workarounds, I see two:
Option 1 - Customise the routing
Taken straight from the docs, you can modify your page directive slightly in the .cshtml in order to customise the routing:
@page "{handler?}"
This option states that for the given page, use an extra segment for specifying the handler name, rather than setting it as a query-string parameter. That means your calls will change from e.g. /PageName?handler=handlerName
to /PageName/Handler
. The ?
in the {handler?}
expression from the code-snippet simply states that a handler name is optional and will therefore default to e.g. OnGetAsync
.
This option works because there is no longer a query-string value for the browser to trash, but yet the handler name is captured within the route itself.
Option 2 - Use a hidden input
When submitting a form using GET to a defined action URL, the browser builds up a query-string from the controls that live within the form. This gives the option for adding a new hidden input field to the form:
<form method="get">
<input type="hidden" name="handler" value="search" />
<input type="text" name="search" />
<input type="submit" value="Ara" />
</form>
Here, I've removed the asp-page-handler
and added a hidden input that will end up setting the query-string value of handler
to search
, which builds up a query-string that will match for OnGetSearchAsync
in your example.