web-dev-qa-db-fra.com

Comment fonctionne @ Html.BeginForm ()?

Je suis très nouveau sur ASP.NET, je viens de commencer le tutoriel MVC aujourd'hui sur asp.net. Je suis arrivé ici http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/examining-the-edit-methods-and-edit-view

Jusqu'ici tout va bien, le problème:

Dans ma vue, j'ai le code suivant (Le modèle est défini sur la vue avec @model MyFirstMVC4.Models.Movie)

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Movie</legend>

        @Html.HiddenFor(model => model.ID)

        //... bla bla html input
        <p>
             <input type="submit" value="Save" />
        </p>
    </fieldset>
}

Mon MovieController 

    // Shows the view
    public ActionResult Edit(int id = 0)
    {
        Movie movie = db.Movies.Find(id);
        if (movie == null)
        {
            return HttpNotFound();
        }
        return View(movie);
    }

    //
    // POST: /Movie/Edit/5

    [HttpPost] // Handles the view above
    public ActionResult Edit(Movie movie)
    {
        if (ModelState.IsValid)
        {
            db.Entry(movie).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(movie);
    }

Et voici la question: comment diable transfère-t-il l'objet Movie à la méthode POST ci-dessus?! Quand j'observe le côté client, il y a

<form action = "/Movie/Edit/1" ... />

Ici, je ne comprends pas pourquoi action = url de la même page d’affichage?! 1 Du côté du serveur, il n’ya que Html.BeginForm (): ( Comment réalise-t-on la méthode d’action à publier et quels paramètres de route passer? Cela fonctionne, je ne sais pas pourquoi

19
Ivan Prodanov

La version de BeginForm dans le code, , Sans paramètre, envoie un HTTP POST à l'URL actuelle. Ainsi, si la vue est une réponse à /Movie/Edit/5, la balise de formulaire d'ouverture ressemblera à ceci: :< form action="/Movie/Edit/5" method="post">

L'assistant HTML BeginForm demande au moteur de routage comment atteindre l'action Edit du MovieController. En coulisse, il utilise la méthode GetVirtualPath sur les routesproperty exposées par RouteTable - c’est là que votre application Web a enregistré tous ses itinéraires dans Global.asax. Si vous faites tout cela sans aide HTML, vous devez écrire tout le code Suivant:

  @{
 var context = this.ViewContext.RequestContext;
  var values = new RouteValueDictionary{
  { "controller", "movie" }, { "action", "edit" }
 };
  var path = RouteTable.Routes.GetVirtualPath(context, values);
 }
 <form action="@path.VirtualPath" method="get">
  ...
 </form>

Vous avez demandé comment l'objet movie est transmis. Que l'on appelle modèle de liaison. Lorsque vous avez une action avec un paramètre, le moteur d'exécution MVC utilise un classeur de modèle pour générer le paramètre Vous pouvez avoir plusieurs classeurs de modèles enregistrés dans le moteur d'exécution MVC pour différents types De modèles, mais le cheval de bataille par défaut sera la DefaultModelBinder.

Dans le cas d'un objet Movie , Le classeur de modèle par défaut inspecte le film et recherche toutes les propriétés de film disponibles À des fins de liaison. Conformément à la convention de dénomination que vous avez examinée précédemment, le classeur de modèle par défaut peut automatiquement convertir et déplacer les valeurs de la demande dans un objet film (le classeur de modèle peut Créer également une instance de l'objet à renseigner) . En d'autres termes Lorsque le classeur de modèle voit qu'un film a une propriété Title, il recherche une valeur nommée «Title» dans la demande. Notez que le classeur de modèle a l'apparence «dans la requête» et non «dans la collection. Form ». Le classeur de modèle utilise des composants appelés fournisseurs de valeur pour rechercher des valeurs dans Différentes zones d'une requête . Le classeur de modèle peut examiner les données de routage, la chaîne de requête et la collection de formulaires Vous pouvez également ajouter des fournisseurs de valeur personnalisés si vous le souhaitez.

38
Vlado Pandžić

Lorsque vous appelez BeginForm() sans aucun paramètre, il utilise par défaut le même contrôleur/la même action que ceux utilisés pour afficher la page en cours. Cela suppose que vous aurez une action avec le nom correct sur votre contrôleur qui acceptera les publications (ce que vous faites). Il utilise la RouteValues pour le faire.

Il lie automatiquement chaque contrôle d'entrée (par nom) aux paramètres de l'action acceptant la publication - ou, dans votre cas, aux propriétés du paramètre de l'objet pour l'action acceptant la publication.

9
Nick Albrecht

L'attribut [HttpPost] est attribué à l'action à appeler - POST - submit du formulaire.

pour comprendre le fonctionnement de @using (Html.BeginForm()), vous devez savoir sur quelle page il se trouve déjà. utiliser @using (Html.BeginForm()) dans 2 vues différentes reviendra sur deux contrôleurs différents

4
Scott Selby

Nous pouvons créer des formulaires en tapant du code HTML simple ou des aides HTML. L'un d'eux, Html.BeginForm (); c'est un peu étrange parce que vous pouvez en fait l'envelopper dans une instruction using car ce helper particulier retourne un objet qui implémente IDisposable en C #. D'abord, il écrit avec la balise d'ouverture. Et en bas, lorsque les appels de code générés disposent de cet objet, c’est le moment où il écrira la balise de formulaire de fermeture. Donc, BeginForm me donne un objet qui écrira ma balise de formulaire d'ouverture et ma balise de fermeture. Après cela, vous ne vous souciez plus de rien, vous pouvez simplement vous concentrer sur les étiquettes et les entrées.

0
Eldiyar Talantbek