Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Razor Pages, form page handler not working with GET method

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>
like image 748
user3402183 Avatar asked Jun 12 '18 10:06

user3402183


People also ask

How do you call a method in razor pages?

Razor pages have handler-methods which are HTTP verbs. So to call a method from your page you need to put On followed by the http verb you want then your method name . And in your view pass the name to the asp-page-handler without the OnPost or OnGet prefix or Async suffix.

What method would you use to handle form submission in a PageModel?

The PageModel consists of two Action Handler methods. This Handler method handles the GET calls, for this particular example it is not required and hence left empty. This Handler method handles the POST call when the Submit Button is clicked and the Form is submitted.

What is OnGetAsync?

When a request is made for the page, the OnGetAsync method returns a list of movies to the Razor Page. On a Razor Page, OnGetAsync or OnGet is called to initialize the state of the page. In this case, OnGetAsync gets a list of movies and displays them.


1 Answers

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.

like image 128
Kirk Larkin Avatar answered Sep 28 '22 02:09

Kirk Larkin