2010-11-24 4 views
12

Je me demande comment vous pouvez procéder à l'implémentation de plusieurs actions lors de la soumission d'un formulaire dans asp.net mvc 3 RC.Comment optimiser l'implémentation Enregistrer | Enregistrer et fermer | Annuler les actions de formulaire dans ASP.NET MVC 3 RC

Si j'édite un utilisateur, par exemple, j'aimerais avoir une barre d'action avec les boutons suivants;

"Enregistrer" | "Enregistrer et fermer" | "Annuler"

Enregistrer - Envoie le formulaire et enregistre, pour revenir à l'écran d'édition. Peut être facilement implémenté en tant que bouton d'entrée/de soumission standard. Rien de spécial ici.

code du contrôleur pour cela pourrait ressembler

public ActionResult Edit(UserViewModel model) 
{ 
    ... 
    return RedirectToAction("Edit", model.Id"); 
} 

Annuler - Il suffit de vous revenir à l'écran précédent. Je pensais à utiliser une balise d'ancrage pour cela.

<a href="@Request.UrlReferrer" class="button">Cancel</a> 

Mais je suis perplexe sur la façon de mettre en œuvre « Enregistrer et fermer » lorsque vous devez présenter les mêmes données de formulaire. Je me demandais d'avoir un paramètre proche nullable peut-être? Mais comment soumettre ce paramètre supplémentaire avec le formulaire dans ce cas?

Si possible, j'aimerais avoir une seule action de formulaire pour gérer le soumettre comme dans la maquette ci-dessus.

Je suis également intéressé si quelqu'un d'autre a trouvé un bon modèle d'interaction utilisateur autour de cette idée.

Solution

Je fini par utiliser la suggestion d'Omar ci-dessous, mais au lieu de passer dans une chaîne que je pris dans un ENUM, donc je ne dois pas faire des vérifications de chaîne dans tous mes contrôleurs.

public ActionResult Edit(UserViewModel model, FormAction actionType) 
{ 
    // pre-check 
    if (actionType == FormAction.Cancel) 
    // just return user to previous view and don't save. 

    // Save code 

    if (actionType == FormAction.Save) 
    return ... 
    else if (actionType == FormAction.SaveAndClose) 
    .... 
} 

Parce que je voulais un texte plus favorable « Enregistrer et fermer » sur le bouton <input> mais je voulais utiliser un ENUM je mis en œuvre un ModelBinder personnalisé pour FormAction qui a fait l'analyse syntaxique.

Je n'ai pas utilisé de balise <button> parce que le thème était déjà en place pour les balises <input>.

Répondre

18

Vous pouvez avoir plusieurs boutons d'envoi dans un formulaire avec le même attribut name mais différents attributs value. Quel que soit le bouton cliqué, le value associé sera publié sur le serveur.

Vous pouvez utiliser un simple lien pour Cancel mais je l'incluerai de toute façon.

<input type="submit" name="actionType" value="Save" /> 
<input type="submit" name="actionType" value="Save and Close" /> 
<input type="submit" name="actionType" value="Cancel" /> 

Et dans votre action, testez les valeurs.

public ActionResult Edit(string actionType) 
{ 
    if(actionType == "Save") 
    { 
     // Save action 
    } 
    else if (actionType == "Save and Close") 
    { 
     // Save and quit action 
    } 
    else 
    { 
     // Cancel action 
    } 
} 

Si vous ne souhaitez pas avoir le long texte dans l'attribut value, vous pouvez utiliser la balise HTML <button> standard qui vous permet de définir une valeur distincte et texte séparé.

+0

http://stackoverflow.com/questions/2423041/using-two- soumettre-boutons-à l'intérieur-unique-forme/2426152 # 2426152 – takepara

+0

Merci Omar. C'était exactement ce que je voulais. À votre santé! –

+0

Mis à jour ma question avec la solution finale basée sur cette approche. Assez similaire, juste nettoyé pour utiliser une énumération au lieu de chaînes. –

5

La suggestion de @Omar est géniale. Voici comment je l'ai fait un peu plus générique dans le cas où je voulais une confirmation lorsque l'utilisateur est invité à supprimer un objet. Remarque! dans le HttpPost je tire à nouveau l'objet plutôt que d'utiliser l'élément passé à la méthode. Vous pouvez réduire un appel DB en ayant la vue contenant toutes les propriétés de sorte que "Item" soit rempli.

Voici la vue Modèle

public class DeleteViewModel<T> { 
    public string ActionType { get; set; } 
    public T Item { get; set; } 
} 

Contrôleur

public ActionResult Delete(int id) { 
     DeleteViewModel<Category> model = new DeleteViewModel<Category>() { 
      Item = categoryRepository.Categories.FirstOrDefault(x => x.CategoryID == id) 
     }; 
     return View(model); 
    } 

    [HttpPost] 
    public ActionResult Delete(DeleteViewModel<Category> model) { 
     if (model.ActionType == "Cancel") 
      return RedirectToAction("Index"); 
     else if (model.ActionType == "Delete") { 
      var cat = categoryRepository.Categories.FirstOrDefault(x => x.CategoryID == model.Item.CategoryID); 
      categoryRepository.Delete(cat); 
      return RedirectToAction("Index"); 
     }   
     //Unknown Action 
     return RedirectToAction("Index"); 
    } 

Voir

<div class="actions"> 
     <div class="actions-left"><input type="submit" value="Cancel" name="ActionType"/></div> 
     <div class="actions-right"><input type="submit" value="Delete" name="ActionType" /></div> 
    </div> 
+0

J'aime mieux cette solution, car elle vous permet de passer le modèle sur lequel vous jouez. – Buzzer

Questions connexes