Razor Pages, form page handler not working with GET method

13,973

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.

Share:
13,973
user3402183
Author by

user3402183

Updated on June 23, 2022

Comments

  • user3402183
    user3402183 almost 2 years

    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>