Pregunta ¿Cómo maneja múltiples botones de envío en ASP.NET MVC Framework?


¿Hay alguna manera fácil de manejar múltiples botones de envío desde la misma forma? Ejemplo:

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" value="Send" />
<input type="submit" value="Cancel" />
<% Html.EndForm(); %>

¿Alguna idea de cómo hacer esto en ASP.NET Framework Beta? Todos los ejemplos que he buscado tienen botones individuales en ellos.


652
2018-01-14 11:58


origen


Respuestas:


Aquí hay una solución basada principalmente en atributos limpios para el problema del botón de envío múltiple basado en gran medida en la publicación y los comentarios de Maartin Balliauw.

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MultipleButtonAttribute : ActionNameSelectorAttribute
{
    public string Name { get; set; }
    public string Argument { get; set; }

    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
    {
        var isValidName = false;
        var keyValue = string.Format("{0}:{1}", Name, Argument);
        var value = controllerContext.Controller.ValueProvider.GetValue(keyValue);

        if (value != null)
        {
            controllerContext.Controller.ControllerContext.RouteData.Values[Name] = Argument;
            isValidName = true;
        }

        return isValidName;
    }
}

maquinilla de afeitar:

<form action="" method="post">
 <input type="submit" value="Save" name="action:Save" />
 <input type="submit" value="Cancel" name="action:Cancel" />
</form>

y controlador:

[HttpPost]
[MultipleButton(Name = "action", Argument = "Save")]
public ActionResult Save(MessageModel mm) { ... }

[HttpPost]
[MultipleButton(Name = "action", Argument = "Cancel")]
public ActionResult Cancel(MessageModel mm) { ... }

Actualizar:  Páginas de navaja busca proporcionar la misma funcionalidad lista para usar. Para un nuevo desarrollo, puede ser preferible.


550
2017-08-18 17:00



Asigne un nombre a sus botones de envío y luego inspeccione el valor enviado en su método de controlador:

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" name="submitButton" value="Send" />
<input type="submit" name="submitButton" value="Cancel" />
<% Html.EndForm(); %>

publicando en

public class MyController : Controller {
    public ActionResult MyAction(string submitButton) {
        switch(submitButton) {
            case "Send":
                // delegate sending to another controller action
                return(Send());
            case "Cancel":
                // call another action to perform the cancellation
                return(Cancel());
            default:
                // If they've submitted the form without a submitButton, 
                // just return the view again.
                return(View());
        }
    }

    private ActionResult Cancel() {
        // process the cancellation request here.
        return(View("Cancelled"));
    }

    private ActionResult Send() {
        // perform the actual send operation here.
        return(View("SendConfirmed"));
    }

}

EDITAR:

Para extender este enfoque al trabajo con sitios localizados, aísle sus mensajes en otro lugar (por ejemplo, compilando un archivo de recursos en una clase de recursos de tipo fuerte)

Luego modifique el código para que funcione como:

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" name="submitButton" value="<%= Html.Encode(Resources.Messages.Send)%>" />
<input type="submit" name="submitButton" value="<%=Html.Encode(Resources.Messages.Cancel)%>" />
<% Html.EndForm(); %>

y su controlador debería verse así:

// Note that the localized resources aren't constants, so 
// we can't use a switch statement.

if (submitButton == Resources.Messages.Send) { 
    // delegate sending to another controller action
    return(Send());

} else if (submitButton == Resources.Messages.Cancel) {
     // call another action to perform the cancellation
     return(Cancel());
}

438
2018-01-14 14:02



Puede verificar el nombre en la acción como se ha mencionado, pero puede considerar si este es un buen diseño. Es una buena idea considerar la responsabilidad de la acción y no unir demasiado este diseño a aspectos de la interfaz de usuario, como los nombres de botones. Así que considere usar 2 formularios y 2 acciones:

<% Html.BeginForm("Send", "MyController", FormMethod.Post); %>
<input type="submit" name="button" value="Send" />
<% Html.EndForm(); %>

<% Html.BeginForm("Cancel", "MyController", FormMethod.Post); %>
<input type="submit" name="button" value="Cancel" />
<% Html.EndForm(); %>

Además, en el caso de "Cancelar", generalmente no está procesando el formulario y va a una nueva URL. En este caso, no necesita enviar el formulario y solo necesita un enlace:

<%=Html.ActionLink("Cancel", "List", "MyController") %>

115
2018-01-14 12:26



Eilon sugiere que puedes hacerlo así:

Si tienes más de un botón,   puede distinguir entre ellos dando   cada botón un nombre:

<input type="submit" name="SaveButton" value="Save data" />
<input type="submit" name="CancelButton" value="Cancel and go back to main page" />

En tu método de acción del controlador,   puede agregar parámetros nombrados después del   Nombres de etiquetas de entrada de HTML:

public ActionResult DoSomeStuff(string saveButton, string
cancelButton, ... other parameters ...)
{ ... }

Si cualquier valor se publica en uno de   esos parámetros, eso significa que   botón fue el que hizo clic.   El navegador web solo publicará un valor   Para el uno botón que hizo clic.   Todos los demás valores serán nulos.

if (saveButton != null) { /* do save logic */ }
if (cancelButton != null) { /* do cancel logic */ }

Me gusta este método, ya que no depende de la propiedad de valor de los botones de envío, que es más probable que cambie que los nombres asignados y no requiere javascript para ser habilitado

Ver: http://forums.asp.net/p/1369617/2865166.aspx#2865166


92
2018-01-20 21:30



Acabo de escribir una publicación sobre eso: Varios botones de envío con ASP.NET MVC:

Básicamente, en lugar de usar ActionMethodSelectorAttribute, Estoy usando ActionNameSelectorAttribute, lo que me permite fingir que el nombre de la acción es lo que quiero que sea. Por suerte, ActionNameSelectorAttribute no solo me hace especificar el nombre de la acción, sino que puedo elegir si la acción actual coincide con la solicitud.

Entonces está mi clase (por cierto, no me gusta mucho el nombre):

public class HttpParamActionAttribute : ActionNameSelectorAttribute {
    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo) {
        if (actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase))
            return true;

        if (!actionName.Equals("Action", StringComparison.InvariantCultureIgnoreCase))
            return false;

        var request = controllerContext.RequestContext.HttpContext.Request;
        return request[methodInfo.Name] != null;
    }
} 

Para usar simplemente defina un formulario como este:

<% using (Html.BeginForm("Action", "Post")) { %>
  <!— …form fields… -->
  <input type="submit" name="saveDraft" value="Save Draft" />
  <input type="submit" name="publish" value="Publish" />
<% } %> 

y controlador con dos métodos

public class PostController : Controller {
    [HttpParamAction]
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult SaveDraft(…) {
        //…
    }

    [HttpParamAction]
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Publish(…) {
        //…
    } 
}

Como puede ver, el atributo no requiere que especifique nada en absoluto. Además, el nombre de los botones se traduce directamente a los nombres del método. Además (no lo he intentado), estos deberían funcionar también como acciones normales, para que pueda publicar en cualquiera de ellos directamente.


39
2018-03-15 19:03



Sugeriría partes interesadas echar un vistazo a la solución de Maarten Balliauw. Creo que es muy elegante.

En caso de que el enlace desaparezca, está usando el MultiButton atributo aplicado a una acción del controlador para indicar con qué botón hacer clic se debe relacionar esa acción.


34
2018-04-22 15:36



es corto y suite:

Fue respondido por Jeroen Dop

<input type="submit" name="submitbutton1" value="submit1" />
<input type="submit" name="submitbutton2" value="submit2" />

y hazlo así en código behinde

 if( Request.Form["submitbutton1"] != null)
{
    // Code for function 1
}
else if(Request.Form["submitButton2"] != null )
{
       // code for function 2
}

Buena suerte.


23
2018-05-28 09:41



Debería poder nombrar los botones y darles un valor; luego mapea este nombre como un argumento para la acción. Alternativamente, use 2 enlaces de acción separados o 2 formularios.


19
2018-01-14 12:07



Podrías escribir:

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" name="button" value="Send" />
<input type="submit" name="button" value="Cancel" />
<% Html.EndForm(); %>

Y luego en la página comprueba si el nombre == "Enviar" o el nombre == "Cancelar" ...


12
2018-01-14 12:11