ASP.NET MVC ActionLink y método de publicación

97

¿Alguien puede decirme cómo puedo enviar valores al controlador usando ActionLink y el método POST?
No quiero usar botones.
Supongo que tiene algo con jquery.

šljaker
fuente
1
Escribí un método que es similar a Html.ActionLink, solo que crea un formulario POST con el botón Enviar. Veré si puedo dar la opción de reemplazar el botón con el enlace que envía el formulario. Vea aquí: stackoverflow.com/questions/3449807/…
nikib3ro

Respuestas:

58

No puede usar un ActionLinkporque eso solo representa una <a>etiqueta de anclaje .
Puede usar una publicación de jQuery AJAX .
O simplemente llame al método de envío del formulario con o sin jQuery (que no sería AJAX), tal vez en el onclickcaso de cualquier control que desee.

AUSteve
fuente
70

Si está utilizando ASP MVC3, puede utilizar un Ajax.ActionLink (), que le permite especificar un método HTTP que puede establecer en "POST".

Aidos
fuente
45
Tenga en cuenta que para que esto funcione, tendrá que incluir uno de los archivos javascript ajax, por ejemplo " jquery.unobtrusive-ajax.min.js". De lo contrario, continuará haciendo un GET en lugar de un POST cuando se haga clic. La sintaxis para hacer el enlace sería como:@Ajax.ActionLink("Delete", "Delete", new { id = item.Id }, new AjaxOptions {HttpMethod = "POST"})
CodingWithSpike
1
el ajax discreto funcionó bien PERO tuve que usar el enlace de acción un poco diferente, pasando un Diccionario como parámetro en lugar de este objeto AjaxOptions: stackoverflow.com/a/10657891/429521 Además, tuve que pasar los atributos ajax a mano para que el JS podía detectar y anular los eventos de clic, lo eran "data-ajax"="true, "data-ajax-url"=<your link> and "data-ajax-method"="Post". Por cierto, estoy usando ASP.NET MVC 3
Felipe Sabino
1
@CokoBWare este stackoverflow.com/questions/10507737/… ? ¿De Verdad? No parece estar roto para mí ...
Felipe Sabino
20

Puede usar jQuery para hacer una POST para todos sus botones. Solo dales el mismo nombre CssClass.

Utilice "devolver falso"; al final de su evento onclick javascript si desea hacer un RedirectToAction del lado del servidor después de la publicación, de lo contrario, simplemente devuelva la vista.

Código Razor

@using (Html.BeginForm())
{
    @Html.HiddenFor(model => model.ID) 
    @Html.ActionLink("Save", "SaveAction", "MainController", null, new { @class = "saveButton", onclick = "return false;" })
}

Código JQuery

$(document).ready(function () {
        $('.saveButton').click(function () {
            $(this).closest('form')[0].submit();
        });
    });

C#

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult SaveAction(SaveViewModel model)
{
    // Save code here...

    return RedirectToAction("Index");
    //return View(model);
}
Idris
fuente
@ goodies4uall De hecho, y esta respuesta hace precisamente eso. :) La clase CSS se llama "saveButton" (quizás un nombre engañoso), pero se usa una etiqueta de anclaje para iniciar la acción
Savantes
17

@Aidos tenía la respuesta correcta, solo quería dejarlo en claro, ya que está oculto dentro de un comentario en su publicación hecho por @CodingWithSpike.

@Ajax.ActionLink("Delete", "Delete", new { id = item.ApkModelId }, new AjaxOptions { HttpMethod = "POST" })
goodies4uall
fuente
6

Aquí había una respuesta incorporada en el proyecto ASP.NET MVC 5 predeterminado que creo que logra mis objetivos de estilo muy bien en la interfaz de usuario. Envíe el formulario usando javascript puro a algún formulario que lo contenga.

@using (Html.BeginForm("Logout", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" }))
{
   <a href="javascript:document.getElementById('logoutForm').submit()">
      <span>Sign out</span>
   </a>
}

El caso de uso que se muestra completamente es un menú desplegable de cierre de sesión en la barra de navegación de una aplicación web.

@using (Html.BeginForm("Logout", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" }))
{
    @Html.AntiForgeryToken()

    <div class="dropdown">
        <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
            <span class="ma-nav-text ma-account-name">@User.Identity.Name</span>
            <i class="material-icons md-36 text-inverse">person</i>
        </button>

        <ul class="dropdown-menu dropdown-menu-right ma-dropdown-tray">
            <li>
                <a href="javascript:document.getElementById('logoutForm').submit()">
                    <i class="material-icons">system_update_alt</i>
                    <span>Sign out</span>
                </a>
            </li>
        </ul>
    </div>
}
daniel.caspers
fuente
3

ActionLink nunca disparará la publicación. Siempre activa la solicitud GET.

Navish Rampal
fuente
2

Utilice el siguiente enlace Llamar a la acción:

<%= Html.ActionLink("Click Here" , "ActionName","ContorllerName" )%>

Para enviar los valores del formulario, utilice:

 <% using (Html.BeginForm("CustomerSearchResults", "Customer"))
   { %>
      <input type="text" id="Name" />
      <input type="submit" class="dASButton" value="Submit" />
   <% } %>

Enviará los datos al controlador del cliente y la acción CustomerSearchResults.

Navish Rampal
fuente
1

Utilice este enlace dentro de Ajax.BeginForm

@Html.ActionLink(
    "Save", 
    "SaveAction", 
    null, 
    null, 
    onclick = "$(this).parents('form').attr('action', $(this).attr('href'));$(this).parents('form').submit();return false;" })

;)

Alexey Smolyakov
fuente
1

Mi solución a este problema es bastante simple. Tengo una página que hace una búsqueda de cliente uno por todo el correo electrónico y el otro por un parcial, el parcial extrae y muestra una lista, la lista tiene un enlace de acción que apunta a un resultado de acción llamado GetByID y pasa la identificación

GetByID extrae los datos del cliente seleccionado y luego regresa

return View("Index", model); 

cuál es el método de publicación

DJ_PLaying
fuente
1

Este ha sido un problema difícil de resolver para mí. ¿Cómo puedo crear un enlace dinámico en razor y html que pueda llamar a un método de acción y pasar un valor o valores a un método de acción específico? Consideré varias opciones, incluido un ayudante html personalizado. Se me ocurrió una solución simple y elegante.

La vista

@model IEnumerable<MyMvcApp.Models.Product>

@using (Html.BeginForm()) {

     <table>
         <thead>
             <tr>
                 <td>Name</td>
                 <td>Price</td>
                 <td>Quantity</td>
            </tr>
        </thead>
        @foreach (Product p in Model.Products)
        {
            <tr>
                <td><a href="@Url.Action("Edit", "Product", p)">@p.Name</a></td>
                <td>@p.Price.ToString()</td>
                <td>@p.Quantity.ToString()</td>
            </tr>
         }
    </table>
}

El método de acción

public ViewResult Edit(Product prod)
{
    ContextDB contextDB = new ContextDB();

    Product product = contextDB.Products.Single(p => p.ProductID == prod.ProductId);

    product = prod;

    contextDB.SaveChanges();

    return View("Edit");
}

El punto aquí es que a Url.Action no le importa si el método de acción es GET o POST. Accederá a cualquier tipo de método. Puedes pasar tus datos al método de acción usando

@Url.Action(string actionName, string controllerName, object routeValues)

el objeto routeValues. He probado esto y funciona. No, técnicamente no está haciendo una publicación o enviando el formulario, pero si el objeto routeValues ​​contiene sus datos, no importa si es una publicación o un get. Puede utilizar una firma de método de acción en particular para seleccionar el método correcto.

wayne.blackmon
fuente
1
Probé su muestra y el navegador envía GET al servidor, incluso el formulario tiene el tipo de publicación. Si actionMethod en el controlador tiene el atributo [HttpPost], la solicitud falla porque no se encuentra la ruta.
Vitaliy Markitanov
1

He hecho el mismo problema usando el siguiente código:

@using (Html.BeginForm("Delete", "Admin"))
{
       @Html.Hidden("ProductID", item.ProductID)
       <input type="submit" value="Delete" />
}
isxaker
fuente
Si tiene muchos elementos en la página, deberá ajustar cada uno de ellos en un formulario y, como resultado, se generarán muchos formularios. También <input type = submit> representa el botón, no el enlace.
Vitaliy Markitanov
@VitaliyMarkitanov, ¿sugieres usar jQuery ajax?
isxaker
Mire mi publicación a continuación en este hilo, expliqué mi solución allí.
Vitaliy Markitanov
En el proyecto de muestra MVC, esto es casi exactamente lo que hacen ellos también
Maya
1

Esta es mi solución al problema. Este es un controlador con 2 métodos de acción.

public class FeedbackController : Controller
{
public ActionResult Index()
{
   var feedbacks =dataFromSomeSource.getData;
   return View(feedbacks);
}

[System.Web.Mvc.HttpDelete]
[System.Web.Mvc.Authorize(Roles = "admin")]
public ActionResult Delete([FromBody]int id)
{
   return RedirectToAction("Index");
}
}

En Vista, renderizo la estructura siguiente.

<html>
..
<script src="~/Scripts/bootbox.min.js"></script>
<script>
function confirmDelete(id) {
  bootbox.confirm('@Resources.Resource.AreYouSure', function(result) {
    if (result) {
      document.getElementById('idField').value = id;
      document.getElementById('myForm').submit();
    }
  }.bind(this));
}
</script>

@using (Html.BeginForm("Delete", "Feedback", FormMethod.Post, new { id = "myForm" }))
{
  @Html.HttpMethodOverride(HttpVerbs.Delete)
  @Html.Hidden("id",null,new{id="idField"})
  foreach (var feedback in @Model)
  {
   if (User.Identity.IsAuthenticated && User.IsInRole("admin"))
   {
    @Html.ActionLink("Delete Item", "", new { id = @feedback.Id }, new { onClick = "confirmDelete("+feedback.Id+");return false;" })
   }
  }
...
</html>

Punto de interés en Razor View :

  1. Función de JavaScript confirmDelete(id)que se llama cuando @Html.ActionLinkse hace clic en el enlace generado con ;

  2. confirmDelete()función requerida id del elemento en el que se hace clic. Este elemento se pasa deonClick controlador. confirmDelete("+feedback.Id+");return false;Preste atención. El controlador devuelve falso para evitar la acción predeterminada, que es obtener la solicitud al objetivo. OnClickEl evento para botones podría adjuntarse con jQuery para todos los botones de la lista como alternativa (probablemente será incluso mejor, ya que habrá menos texto en la página HTML y los datos podrían pasarse a través de un data-atributo).

  3. Forma tiene id=myForm, para encontrarlo en confirmDelete().

  4. La forma incluye @Html.HttpMethodOverride(HttpVerbs.Delete)para usar el HttpDeleteverbo, como acción marcada con HttpDeleteAttribute.

  5. En la función JS, utilizo la confirmación de la acción (con la ayuda de un complemento externo, pero la confirmación estándar también funciona bien. No olvide usar bind()en la devolución de llamada o var that=this(lo que prefiera).

  6. La forma tiene un elemento oculto con id='idField'y name='id'. Entonces, antes de que result==truese envíe el formulario después de la confirmación ( ), el valor del elemento oculto se establece en el valor del argumento pasado y el navegador enviará datos al controlador como este:

URL de solicitud :http://localhost:38874/Feedback/Delete

Método de solicitud : Código de estado POST: 302 encontrado

Encabezados de respuesta

Ubicación: / Host de comentarios: localhost: 38874 Formulario de datos X-HTTP-Method-Override: DELETE id: 5

Como ve, es una solicitud POST con X-HTTP-Method-Override: DELETE y los datos en el cuerpo establecidos en "id: 5". La respuesta tiene un código 302 que redirige a la acción de índice, con esto actualiza su pantalla después de eliminar.

Vitaliy Markitanov
fuente
0

Recomendaría mantenerse puro con los principios REST y usar una eliminación HTTP para sus eliminaciones. Desafortunadamente, HTML Specs solo tiene HTTP Get & Post. Una etiqueta solo puede obtener HTTP. Una etiqueta de formulario puede realizar un HTTP Get o Post. Afortunadamente, si usa ajax, puede hacer una eliminación HTTP y esto es lo que recomiendo. Consulte la siguiente publicación para obtener más detalles: Http Deletes

coding4fun
fuente
0

Llamar a $ .post () no funcionará ya que está basado en Ajax. Por lo tanto, es necesario utilizar un método híbrido para este propósito.

La siguiente es la solución que me está funcionando.

Pasos: 1. Cree una URL para href que llame al método a con la URL y el parámetro 2. Llame a POST normal usando el método JavaScript

Solución:

En .cshtml:

<a href="javascript:(function(){$.postGo( '@Url.Action("View")', { 'id': @receipt.ReceiptId  } );})()">View</a>

Nota: el método anónimo debe estar envuelto en (....) () es decir

(function() {
    //code...
})();

postGo se define como se muestra a continuación en JavaScript. El descanso es simple ..

@ Url.Action ("Ver") crea una URL para la llamada

{'id': @ receiver.ReceiptId} crea parámetros como un objeto que a su vez se convierte en campos POST en el método postGo. Puede ser cualquier parámetro que necesite

En JavaScript:

(function ($) {
    $.extend({
        getGo: function (url, params) {
            document.location = url + '?' + $.param(params);
        },
        postGo: function (url, params) {
            var $form = $("<form>")
                .attr("method", "post")
                .attr("action", url);
            $.each(params, function (name, value) {
                $("<input type='hidden'>")
                    .attr("name", name)
                    .attr("value", value)
                    .appendTo($form);
            });
            $form.appendTo("body");
            $form.submit();
        }
    });
})(jQuery);

URL de referencia que he usado para postGo

GET / POST no ajax usando jQuery (¿complemento?)

http://nuonical.com/jquery-postgo-plugin/

Tejasvi Hegde
fuente
0

jQuery.post()funcionará si tiene datos personalizados. Si desea publicar un formulario existente, es más fácil de usar ajaxSubmit().

Y no tiene que configurar este código en ActionLinksí mismo, ya que puede adjuntar un controlador de enlace en el document.ready()evento (que es un método preferido de todos modos), por ejemplo, usando el $(function(){ ... })truco jQuery.

queen3
fuente
0

Encontré esta necesidad de PUBLICAR desde una página de búsqueda (índice) a la página de resultados. No necesitaba tanto como dijo @Vitaliy, pero me indicó la dirección correcta. Todo lo que tenía que hacer era esto:

@using (Html.BeginForm("Result", "Search", FormMethod.Post)) {
  <div class="row">
    <div class="col-md-4">
      <div class="field">Search Term:</div>
      <input id="k" name="k" type="text" placeholder="Search" />
    </div>
  </div>
  <br />
  <div class="row">
    <div class="col-md-12">
      <button type="submit" class="btn btn-default">Search</button>
    </div>
  </div>
}

Mi controlador tenía el siguiente método de firma:

[HttpPost]
public async Task<ActionResult> Result(string k)
Grandizer
fuente
0

Esto se toma del proyecto de muestra MVC

@if (ViewBag.ShowRemoveButton)
      {
         using (Html.BeginForm("RemoveLogin", "Manage"))
           {
              @Html.AntiForgeryToken()
                  <div>
                     @Html.Hidden("company_name", account)
                     @Html.Hidden("returnUrl", Model.returnUrl)
                     <input type="submit" class="btn btn-default" value="Remove" title="Remove your email address from @account" />
                  </div>
            }
        }
maya
fuente