Nouvelles Chroniques d'Amethyste

Penser au Sens, pas au Verbe

Lancer plusieurs actions en MVC

Poster un commentaire

Regardez ce formulaire MVC:

@model Customer
@using (Html.BeginForm("Update", "Home"))
{
    @Html.EditorFor(c => c.FirstName)
    <br />
    <input type="submit" name="SaveWork" id="SaveWork" value="Save Your Work" />
    <input type="submit" name="SaveWork" id="FinishWork" value="Complete" />
}

Avec la classe Customer qui va bien évidemment.

2014-12-03_09-43-09

On dispose de deux boutons subit dans le même formulaire et un champ de saisie.

Le chalenge n’est pas d’activer une action pour chaque bouton (un lien suffirait), mais d’activer une action différente ET émettre le contenu de la zone de saisie. Le code Html généré est le suivant:

<form action="/Home/Update" method="post">
    <input id="FirstName" name="FirstName" type="text" value="" />
    <br />
    <input type="submit" name="SaveWork" id="SaveWork" value="Save Your Work" />
    <input type="submit" name="SaveWork" id="FinishWork" value="Complete" />
</form>

Comme on le voit, l’action est statiquement déterminée au moment du rendu de la page. Donc dans tous les cas l’action présentée sera Index. C’est là que réside le chalenge. Comment différentier les deux situations?

Une première idée pourrait être de bricoler un truc en Javascript. Bref le genre de solution que l’on sent intuitivement pas top et votre intuition a justement raison.

Puisque nous sommes dans un environnement MVC, mieux vaut se servir de MVC et en particulier du Model Binder.

Vous remarquerez que les deux boutons Submit ont le même name. On pourrait donc récupérer une valeur SaveWork dans la signature de l’action et avoir ceci:

public ActionResult Update(Customer customer, string saveWork)
{
    if (saveWork == "Complete")
    {
        // bouton Complete
    }
    else
    {
        // bouton Save Your Work
    }

Bon être dépendant d’un libellé c’est pas terrible. On peut améliorer les choses en modifiant les name:

<input type="submit" name="SaveWork" id="SaveWork" value="Save Your Work" />
<input type="submit" name="CompleteWork" id="FinishWork" value="Complete" />

Et alors:

public ActionResult Update(Customer customer, string saveWork, string completeWork)
{
    if (string.IsNullOrEmpty(saveWork))
    {
        // bouton Complete
    }
    else
    {
        // bouton Save Your Work
    }

 

Une alternative repose sur l’attribut ActionMethodSelectorAttribute qui permet de personnaliser l’algorithme de sélection d’une action dans un contrôleur. Il s’agit d’une classe abstraite, nous allons dériver la notre:

public sealed class CustomActionMethodSelectorAttribute : ActionMethodSelectorAttribute
{
    public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
    {
        throw new NotImplementedException();
    }
}

Nous devons implémenter la logique de sélection dans la méthode IsValidForRequest. Par exemple on aurait ceci:


public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
{
    if (controllerContext.HttpContext.Request.Params.AllKeys.Contains("CompleteWork"))
    {
        return true;
    }
    return false;
}

On garde le dernier Html.  La méthode retourne true si on clique sur le bouton Complete. Le contrôleur est le suivant:

public ActionResult Update(Customer customer)
{
    return View();
}

[ActionName("Update")]
[CustomActionMethodSelector()]
public ActionResult UpdateComplete(Customer customer)
{
    return View("About");
}

Nous avons créé deux méthodes, une pour chaque bouton. L’attribut se charge de faire la sélection.

 Bibliographie

 

Publicités

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s