web-dev-qa-db-fra.com

Razor Pages, le gestionnaire de pages de formulaire ne fonctionne pas avec la méthode GET

J'ai un petit projet ASP.NET Core 2.1 Razor Pages. Je crée une page d'affichage de liste simple avec une fonctionnalité de recherche de base. Dans mon modèle, j'ai 4 gestionnaires de pages (2 d'entre eux sont ajoutés à des fins de débogage):

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();
}

Lorsque le formulaire spécifie method="post" Avec asp-page-handler="search", Le formulaire appelle le gestionnaire approprié (OnPostSearchAsync(String search)). Toutefois, lorsque le formulaire spécifie method="get" Avec asp-page-handler="search", Le formulaire appelle le mauvais gestionnaire (OnGetAsync()). Est-ce prévu? Si oui, comment puis-je appeler un gestionnaire personnalisé tout en utilisant la méthode GET? Peut-être que l'utilisation d'un gestionnaire personnalisé n'est pas nécessaire, mais je pense que je devrais pouvoir le faire si je le souhaite.

Voici le code pertinent dans le fichier .cshtml:

<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>
9
user3402183

En termes de pourquoi cela se produit, cette réponse devrait expliquer ce qui se passe ici. Essentiellement, asp-page-handler configure une URL d'action qui inclut ?handler=search, qui est ensuite supprimé par le navigateur pour les requêtes GET.

En termes de solutions de contournement, j'en vois deux:

Option 1 - Personnaliser le routage

Tiré directement de la documentation, vous pouvez modifier légèrement votre directive de page dans le .cshtml afin de personnaliser le routage:

@page "{handler?}"

Cette option indique que pour la page donnée, utilisez un segment supplémentaire pour spécifier le nom du gestionnaire, plutôt que de le définir comme paramètre de chaîne de requête. Cela signifie que vos appels changeront par exemple /PageName?handler=handlerName à /PageName/Handler. Le ? dans le {handler?} l'expression de l'extrait de code indique simplement qu'un nom de gestionnaire est facultatif et sera donc par défaut par exemple OnGetAsync.

Cette option fonctionne car il n'y a plus de valeur de chaîne de requête à supprimer par le navigateur, mais le nom du gestionnaire est capturé dans l'itinéraire lui-même.

Option 2 - Utilisez une entrée cachée

Lors de la soumission d'un formulaire à l'aide de GET à une URL d'action définie, le navigateur crée une chaîne de requête à partir des contrôles qui vivent dans le formulaire. Cela donne la possibilité d'ajouter un nouveau champ de saisie masqué au formulaire:

<form method="get">
    <input type="hidden" name="handler" value="search" />
    <input type="text" name="search" />
    <input type="submit" value="Ara" />
</form>

Ici, j'ai supprimé le asp-page-handler et a ajouté une entrée masquée qui finira par définir la valeur de chaîne de requête de handler sur search, ce qui crée une chaîne de requête qui correspondra à OnGetSearchAsync dans votre exemple.

14
Kirk Larkin