Olá pessoal, tudo certo?

É algo bem comum um form ter várias ações diferentes, como por exemplo um salvar/excluir.  Contudo, ao setar o atributo action da tag form como mostrado abaixo:

<form action="/Usuario/Salvar"></form>

qualquer submit executará a ação Salvar do controller usuário. Como fazer para que várias ações sejam executadas no mesmo form?

Os exemplos abaixo foram escritos usando dados fictícios e chumbados para não prolongar o desnecessário.

Múltiplos submit's em um form

Conheço quatro formas de fazer isso, algumas menos "bonitas" e uma que acredito ser a melhor opção, que é usando ajax. Mostrarei um exemplo para cada uma dessas opções, começando pelas menos recomendadas até chegar no exemplo com ajax.

Tratando múltiplas ações pelo atributo value

//View

[sourcecode language="html"]
<form action="/Usuario/Submit">

<input type="submit" value="salvar" name="inputSubmit" />
<input type="submit" value="excluir" name="inputSubmit" />

</form>
[/sourcecode]

//Controller

[sourcecode language="csharp"]
public ActionResult Submit(string inputSubmit, FormCollection form)
{
if (inputSubmit == "Salvar")
{
//salvar
}
else
{
//excluir
}
return RedirectToAction("Index");;
}
[/sourcecode]

Saiba que o exemplo acima funciona, entretanto, não considere usar nunca, sério! Esse tipo de validação jamais deve ser feita no controller.

Tratando múltiplas ações utilizando várias tag's form's

//View

[sourcecode language="html"]
<form action="/Home/Salvar" method="post">

<input type="text" name="nome" />
<input type="number" name="idade" />

<input type="hidden" name="id" value="1" />

<button id="btnSalvar">Salvar</button>

</form>

<form action="/Home/Excluir?id=1" method="post">

<button id="btnExcluir">Excluir</button>

</form>
[/sourcecode]

//Controller

[sourcecode language="csharp"]
public ActionResult Salvar(FormCollection form)
{
//To Do
return RedirectToAction("Index");
}
public ActionResult Excluir(int id)
{
//To Do
return RedirectToAction("Index");
}
[/sourcecode]

Pessoalmente, não gosto do exemplo acima. Acho que polui muito meu html, tornando-o difícil de ler.

Tratando múltiplas ações alterando dinamicamente o atributo action do form

//View

[sourcecode language="html"]
<form>

<input type="text" name="nome" />
<input type="number" name="idade" />
<input type="hidden" name="id" />

<button class="submit" data-action="/Usuario/Salvar">Salvar</button>
<button class="submit" data-action="/Usuario/Excluir">Excluir</button>

</form>
[/sourcecode]

//js

[sourcecode language="javascript"]
<script>
$(document).ready(function () {
(function () {
$(".submit").on("click", function (e) {
e.preventDefault();

var action = $(this).data("action");
var form = $("form").first();

form.attr("action", action);
form.submit();
});
})();
});
<script>
[/sourcecode]

//Controller

[sourcecode language="csharp"]
public ActionResult Excluir(int id)
{
//To Do
return RedirectToAction("Index");;
}

public ActionResult Salvar(FormCollection form)
{
//To Do
return RedirectToAction("Index");;
}
[/sourcecode]

No exemplo acima as action's Salvar e Excluir foram implementadas separadas, como devem ser. Usando um atributo data, eu decido qual ação será executada e assim modifico a ação do form antes de fazer o submit. Porém, essa ainda não é a melhor solução na minha opinião.

Tratando múltiplas ações com ajax

//View

[sourcecode language="html"]
<form>

<input type="text" name="nome" />
<input type="number" name="idade" />
<input type="hidden" name="id" />

<button id="btnSalvar">Salvar</button>
<button id="btnExcluir">Excluir"</button>

</form>
[/sourcecode]

//js

[sourcecode language="javascript"]
<script>
$(document).ready(function () {
$("#btnSalvar").on("click", function () {
$.ajax({
url: '/Usuario/Salvar',
type: "POST",
data: $('form').serialize()
}).done(function (data) {
//tratar sucesso
}).fail(function (data) {
//tratar falha
});
});

$("#btnExcluir").on("click", function () {
$.ajax({
url: '/Usuario/Excluir',
data: {id : 1}
}).done(function (data) {
//tratar sucesso
}).fail(function (data) {
//tratar falha
});
});
});
</script>
[/sourcecode]

//Controller

[sourcecode language="csharp"]
public ActionResult Salvar(FormCollection form)
{
//To Do
return RedirectToAction("Index");;
}

public ActionResult Excluir(int id)
{
//To Do
return RedirectToAction("Index");;
}
[/sourcecode]

Era isso que eu queria mostrar, conhece uma abordagem diferente das mostradas ou não concorda com o que foi escrito? Participe deixando um comentário.

Até o próximo post!