Ajouter une galerie d’images à un éditeur de texte enrichi avec Razor Pages

Dans une application Razor Pages, la première idée qui vient naturellement pour la galerie d’images de l’éditeur est un ensemble de gestionnaires nommés sur la page, comme OnGetGallery et OnPostUpload. Pour la galerie de RichTextEditor, ce n’est pas le bon outil, pour deux raisons propres à Razor Pages. Cette page montre quoi faire à la place : l’éditeur sur une Razor Page normale, et les trois routes de la galerie sous forme de points de terminaison dans la même application.
Pourquoi pas des gestionnaires de page
- Les URL ne conviennent pas. Un gestionnaire nommé s’atteint par
/?handler=Upload. Le script d’envoi de l’éditeur envoie vers<base>/upload, et la galerie ajoute?folder=àgalleryEndpointpour chaque liste : des URL de gestionnaires imposeraient donc des modifications des deux côtés. - Chaque gestionnaire POST vérifie un jeton antifalsification. C’est un comportement par défaut de Razor Pages, et un bon. Les requêtes d’envoi et de New folder de l’éditeur sont des XHR que l’éditeur construit lui-même, et la version actuelle ne peut pas y ajouter le jeton. Les gestionnaires nécessiteraient
[IgnoreAntiforgeryToken]sur le modèle de page, ce qui désactive aussi la vérification pour le formulaire Save de la page elle-même.
Les points de terminaison séparent les deux : la page et son formulaire conservent une protection complète, et les routes JSON font leur propre choix, explicite.
Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseStaticFiles();
app.UseRteStaticFiles(); // /uploads, /richtexteditor, /rte-files.js
app.MapRazorPages(); // "/" -> Pages/Index.cshtml; its own form POST keeps antiforgery validation
app.MapRteFiles(); // GET+POST /rte/gallery, POST /rte/upload
app.Run();MapRteFiles() est le même groupe de points de terminaison Minimal API que celui des autres exemples ASP.NET Core : GET et POST /rte/gallery, et POST /rte/upload. UseRteStaticFiles() sert /uploads (uniquement les cinq types d’images), l’éditeur sous /richtexteditor et /rte-files.js.
La page
<link rel="stylesheet" href="/richtexteditor/rte_theme_default.css" />
<script src="/richtexteditor/rte.js"></script>
<script src="/richtexteditor/plugins/all_plugins.js"></script>
<script src="/rte-files.js"></script>L’éditeur est créé plus bas dans la page avec galleryEndpoint: "/rte/gallery". Téléverser des images depuis un éditeur de texte enrichi avec Razor Pages présente cette partie avec le formulaire.
La route de liste
rte.MapGet("/gallery", (HttpContext http, string? folder) =>
Json(RteFiles.List(http, folder)));La réponse est le dossier en JSON : currentFolder, parentFolder (null à la racine), les sous-dossiers et les images avec leur URL, leur nom et leur taille. C’est le même JSON et le même code que dans le guide sur la galerie avec ASP.NET Core, qui explique chaque champ.
Les routes POST et l’antifalsification
// Binding [FromForm] or IFormFile makes .NET 8 demand an antiforgery token on these endpoints.
// The editor's XHRs cannot send one, so it is switched off here and RteFiles checks the
// request's origin instead (see RequireSameOrigin). guide-notes.md has the details.
rte.MapPost("/gallery", (HttpContext http, [FromForm] string? action, [FromForm] string? folder, [FromForm] string? name) =>
Json(RteFiles.CreateFolder(http, action, folder, name)))
.DisableAntiforgery();Voici le second point propre à Razor Pages. AddRazorPages() enregistre les services antifalsification, mais en .NET 8, il n’ajoute pas le middleware antifalsification qu’utilisent les points de terminaison Minimal API. Un point de terminaison qui lie IFormFile ou [FromForm] porte malgré tout des métadonnées antifalsification : sans .DisableAntiforgery(), chaque POST vers lui a donc échoué avec une erreur 500, « contains anti-forgery metadata, but a middleware was not found that supports anti-forgery ». Ajouter plutôt app.UseAntiforgery() transforme cette erreur en 400, car l’éditeur n’envoie pas de jeton. C’est en la désactivant sur ces deux routes, et en vérifiant à la place l’origine de la requête, qu’elles fonctionnent. Envoi d’images sécurisé avec Razor Pages explique cette vérification.
Tester
Lancez le projet d’exemple de ce guide avec dotnet run (SDK .NET 8), ouvrez http://localhost:5303 et cliquez sur Insert Gallery. La boîte de dialogue liste les dossiers et les images sous uploads/. Depuis un shell, la route d’envoi répond sans jeton, contrairement au POST propre à la page :
curl -F "file=@photo.jpg" http://localhost:5303/rte/upload
{"url":"/uploads/photo-4cdaeb3e.jpg"}
curl -s -o /dev/null -w "%{http_code}\n" -d "Html=x" http://localhost:5303/
400Le 400 correspond au refus par Razor Pages d’un envoi de formulaire sans son jeton antifalsification, ce qui est exactement ce que vous voulez pour la page.
Le même guide pour d’autres plateformes
JavaScript · Next.js · PHP · ASP.NET Core · Blazor · MVC 5 · Web Forms