6
votes

ASP.NET Core 2.1 Razor Form, Post n'atteignant pas le contrôleur

J'ai passé une bonne marge de temps à chercher et résoudre ce problème hier sans trouver de solution. Voici le guide que j'ai utilisé comme référence.

Le problème est que mon contrôleur n'atteint pas les données du formulaire. Mon objectif est de prendre les données du formulaire et de les transmettre à mon contrôleur / modèle afin que je puisse utiliser les valeurs dans tout mon code et les stocker dans la base de données. Voici ce que j'ai jusqu'à présent ...

Dans mon Browse.cshtml (View)

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
  Request starting HTTP/1.1 POST https://localhost:5001/browse?game=eevee application/x-www-form-urlencoded 7

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
  Request finished in 1.0139ms 200

info: Microsoft.AspNetCore.Server.Kestrel[32]
  Connection id "0HLJHIUOU6AKO", Request id "0HLJHIUOU6AKO:00000003": the application completed without reading the entire request body.

Dans mon CollectController.cs (Controller) p>

namespace GameLibrary.me.Models

{
public class Collect
{
    public int GameId { get; set; }
  }
}

Dans mon Collect.cs (Modèle)

using System;
using GameLibrary.me.Models;
using Microsoft.AspNetCore.Mvc;

namespace GameLibrary.me.Controllers
{
public class CollectController  : Controller
{
    [HttpGet]
    public IActionResult Collect()
    {
        return View();
    }

    [HttpPost, ValidateAntiForgeryToken]
    public IActionResult Collect(Collect model)
    {

        Console.WriteLine("**********\n"+model.GameId+"\n**********");

        return Content($"Hello {model.GameId}");
    }    
  }
}

EDIT: Voici ce que mon IDE me dit ...

@model Collect

<form asp-action="Collect" asp-controller="Collect" method="post">
<input type="hidden" asp-for="GameId" name="@game.id"/>
<button type="submit" class="dropdown-item btn btn-block">Default</button>
</form>

Toute indication sur ce que je fais mal serait très appréciée ... Puis-je également envoyer plusieurs valeurs via le type de champ masqué, ou devrais-je créer un nouveau type de champ masqué pour chaque valeur?


14 commentaires

quelle est la valeur de l'entrée masquée GameId lors du premier rendu de la page? (l'exemple lié utilise des entrées non cachées pour collecter des données, je crois également que vous voudrez changer la valeur du nom de votre entrée en seulement GameId) De plus, si vous utilisez les outils de débogage de broswer, et regardez le POST de votre contrôleur, la valeur GameId est-elle envoyée?


J'imagine que votre routage a un problème car votre contrôleur s'appelle Collect, la méthode d'index s'appelle Collect, donc lorsque le framework recherche une route, vous dites qu'elle devrait être / Collect / Collect . Vous pouvez également utiliser le nom de base de l'index, comme s'il s'agissait d'une recherche de secours et utiliser HttpRoute pour prédéfinir un nouveau nom. Sauf si vous avez correctement défini ces noms d'itinéraire personnalisés ailleurs.


Je pense que vous avez raison @Greg ... Je viens d'ajouter la réponse de mon IDE à mon message. Je voudrais donc changer l'ASP-ACTION sous forme de rasoir, puis dans mon contrôleur, changer le nom de la méthode pour qu'il corresponde?


@G_P On dirait que ça passe. Dans ce cas, gameID est un int envoyé. Dans ce cas, si je change cela pour être une valeur statique telle que 5, le même problème se produit. Je viens également de mettre à jour ma question avec la réponse de mon IDE.


Si vous mettez un point d'arrêt dans votre méthode de contrôleur Post et qu'il est touché lorsque vous déboguez, ce n'est pas un problème de routage. Si ce n'est pas le cas, essayez de renommer la méthode Post (et de mettre à jour votre formulaire asp-action). Ensuite, si votre point d'arrêt est atteint mais que la valeur n'est pas dans votre variable de modèle, cela est dû au fait que la liaison de modèle ne fonctionne pas. Essayez de renommer I de votre entrée cachée que j'ai mentionnée plus tôt. De plus, à votre question sur les valeurs supplémentaires, oui, ajoutez simplement des entrées masquées supplémentaires si ce sont des valeurs qui sont nécessaires mais ne doivent pas être modifiées par l'utilisateur.


Il semble que vous ayez juste un petit problème avec name = "@ game.id" , qui devrait être value = "@ game.id" , en supposant que game est une variable accessible depuis votre vue rasoir. Vous ne devriez pas du tout définir name - la présence de asp-for gérera cela pour vous.


@KirkLarkin merci kirk, qui a résolu l'INFO de l'IDE "l'application s'est terminée sans lire le corps de la requête en entier." cependant, ma déclaration d'impression dans mon contrôleur n'est toujours pas déclenchée, même par le facteur.


À quoi ressemble la réponse dans Postman?


@G_P J'ai mis un point de rupture sur mon message et je l'ai parcouru, cela ne déclenche pas le point de rupture. J'ai essayé de changer le nom de la méthode asp-action et post en Index, puis j'ai changé les deux en Test. Ne déclenchant toujours pas de point de rupture ...


@KirkLarkin Aucune page trouvée. Veuillez vérifier votre URL.


Pouvez-vous inspecter la page dans les outils de développement de votre navigateur et inclure le code HTML rendu pour votre formulaire dans votre question? Vous pouvez également envisager de rendre votre projet disponible par exemple. GitHub (s'il n'est pas sensible).


@KirkLarkin voici le formulaire


C'est alors le problème. Les tag-helpers ne fonctionnent pas. Voir le docs .


@KirkLarkin a résolu ce problème. Le formulaire s'affiche correctement maintenant. Je vous remercie! Bien que maintenant je suis de retour à: Identifiant de connexion "0HLJHLIES6H1B", Identifiant de demande "0HLJHLIES6H1B: 00000002": l'application s'est terminée sans lire le corps de la requête en entier. Voici le code HTML pour référence: screencast.com/t/W2dzd6CCn0UF Lol, je ne peux pas pense que les balises d'assistance faisaient partie du problème. Une solution si simple. Merci!


3 Réponses :


0
votes

Sur la base de votre exemple, je ne pense pas que vous souhaitiez des actions personnalisées, vous devriez pouvoir atteindre votre objectif avec le mappage de cadre par défaut.

routes.MapRoute(
                "Default",                         // Route name
                "{controller}/{action}/{id}",      // URL with parameters
                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            );

Pour clarifier la magie, le post déclaré method J'utilise un attribut HttpBody , sinon le framework s'attend à ce que le contenu du paramètre soit défini via la chaîne de requête dans l'URL. Le framework par défaut recherche Index lorsqu'un Controller a été touché, si vous n'avez pas besoin de l'URL pour le représenter, alors ne l'utilisez pas.

Le modèle de routage suit généralement :

public class CollectController : Controller
{
     [HttpGet]
     public IActionResult Index() => View();

     [HttpPost]
     public IActionResult Index([FromBody]CollectionModel model) => Content(...);
}

URL:

http : //www.sample.com/Collect ---> L'index initial Get serait touché


0 commentaires

9
votes

Il y avait beaucoup d'aide différente ici, notamment grâce à Kirk Larklin! Trois problèmes empêchaient mon contrôleur de récupérer les données.

  1. Browse.cshtml manquait le @addTagHelpers ... J'ai ajouté ce qui suit:

    public IActionResult Index(Collect model)
    
  2. Mon CollectController.cs manquait une route ... J'ai ajouté ce qui suit:

    [HttpPost, ValidateAntiForgeryToken]
    [Route("Index/Collect")] 
    
  3. Enfin, j'ai renommé ma méthode de publication de contrôleur de 'Collect', ce qui est en conflit avec une autre méthode d'indexation et mis à jour l'action asp dans mon fichier Browse.CSHTML pour qu'elle corresponde.

    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    @addTagHelper *, AuthoringTagHelpers
    

Merci pour toute l'aide!

-Travis W


1 commentaires

Vous avez défini le définisseur Route personnalisé que j'ai mentionné, je suppose que c'est corrigé?



1
votes

Tout d'abord, je passerais le modèle à la vue avec l'ID initialisé:

<form asp-action="Collect" asp-controller="Collect" method="post">
    @Html.HiddenFor(m => m.GameId)
    <button type="submit" class="dropdown-item btn btn-block">Default</button>
</form>

Dans votre vue, mettez à jour le formulaire comme suit:

    public IActionResult Collect()
    {

        return View(new Collect { GameId = "5"});
    }


0 commentaires