ActionLink ASP.NET MVC e metodo post


97

Qualcuno può dirmi come posso inviare valori al controller utilizzando ActionLink e il metodo POST?
Non voglio usare i pulsanti.
Immagino abbia qualcosa con jquery.


1
Ho scritto un metodo simile a Html.ActionLink, solo che crea il modulo POST con il pulsante Invia. Vedrò se posso dare l'opzione per sostituire il pulsante con il link che invia il modulo. Vedi qui: stackoverflow.com/questions/3449807/...
nikib3ro

Risposte:


58

Non puoi usare un ActionLinkperché questo rende solo un anchor <a>tag.
Puoi usare un post jQuery AJAX .
Oppure chiama semplicemente il metodo di invio del modulo con o senza jQuery (che sarebbe non AJAX), forse in onclickcaso di qualsiasi controllo ti piaccia.


70

Se stai usando ASP MVC3 potresti usare un Ajax.ActionLink (), che ti permette di specificare un metodo HTTP che puoi impostare su "POST".


45
Nota che per far funzionare questo, dovrai includere uno dei file javascript ajax, ad esempio " jquery.unobtrusive-ajax.min.js". In caso contrario, continuerà a eseguire un GET invece di un POST quando si fa clic. La sintassi per creare il collegamento sarebbe:@Ajax.ActionLink("Delete", "Delete", new { id = item.Id }, new AjaxOptions {HttpMethod = "POST"})
CodingWithSpike

1
discreto ajax ha funzionato bene ma ho dovuto utilizzare il link azione un po 'diverso, passando un dizionario come parametro al posto di questo AjaxOptions oggetto: stackoverflow.com/a/10657891/429521 Inoltre, ho dovuto passare l'ajax attribuisce a mano in modo che il JS poteva catturare e sovrascrivere gli eventi di clic, lo erano "data-ajax"="true, "data-ajax-url"=<your link> and "data-ajax-method"="Post". A proposito, sto usando ASP.NET MVC 3
Felipe Sabino

1
@CokoBWare questo stackoverflow.com/questions/10507737/... ? veramente? Non sembra essersi rotto per me ...
Felipe Sabino

20

Puoi usare jQuery per fare un POST per tutti i tuoi pulsanti. Basta dare loro lo stesso nome CssClass.

Usa "return false;" alla fine del tuo evento javascript onclick se vuoi fare un RedirectToAction lato server dopo il post, altrimenti torna alla visualizzazione.

Codice del rasoio

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

Codice 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);
}

@ goodies4uall In effetti, e questa risposta fa proprio questo. :) La classe CSS si chiama "saveButton" (forse un nome fuorviante), ma viene utilizzato un tag di ancoraggio per avviare l'azione
Savantes

17

@Aidos aveva la risposta giusta, volevo solo metterlo in chiaro visto che è nascosto all'interno di un commento al suo post fatto da @CodingWithSpike.

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

6

Ecco una risposta inserita nel progetto ASP.NET MVC 5 predefinito, credo che raggiunga bene i miei obiettivi di stile nell'interfaccia utente. Invia il modulo utilizzando javascript puro a un modulo contenente.

@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>
}

Il caso d'uso completamente mostrato è un menu a discesa di disconnessione nella barra di navigazione di un'app 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>
}


2

Utilizzare il seguente collegamento Call the Action:

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

Per inviare i valori del modulo utilizzare:

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

Inoltrerà i dati al controller del cliente e all'azione CustomerSearchResults.


1

Usa questo collegamento all'interno di Ajax.BeginForm

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

;)


1

La mia soluzione a questo problema è abbastanza semplice. Ho una pagina che fa una ricerca di un cliente uno per l'intera email e l'altro da un parziale, il parziale estrae e visualizza un elenco l'elenco ha un collegamento all'azione che punta a un risultato dell'azione chiamato GetByID e passa l'ID

GetByID estrae i dati per il cliente selezionato, quindi restituisce

return View("Index", model); 

che è il metodo post


1

Questo è stato un problema difficile da risolvere per me. Come posso creare un collegamento dinamico in razor e html che possa chiamare un metodo di azione e passare uno o più valori a un metodo di azione specifico? Ho considerato diverse opzioni tra cui un helper html personalizzato. Ho appena trovato una soluzione semplice ed 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>
}

Il metodo d'azione

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");
}

Il punto qui è che Url.Action non si preoccupa se il metodo di azione è un GET o un POST. Accederà a entrambi i tipi di metodo. Puoi passare i tuoi dati al metodo di azione usando

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

l'oggetto routeValues. L'ho provato e funziona. No, tecnicamente non stai scrivendo un post o inviando il modulo, ma se l'oggetto routeValues ​​contiene i tuoi dati, non importa se è un post o un get. È possibile utilizzare una particolare firma del metodo di azione per selezionare il metodo corretto.


1
Ho provato il tuo campione e il browser invia GET al server, anche il modulo ha il tipo Post. Se actionMethod nel controller ha l'attributo [HttpPost], la richiesta non riesce perché la route non è stata trovata.
Vitaliy Markitanov

1

Ho fatto lo stesso problema usando il seguente codice:

@using (Html.BeginForm("Delete", "Admin"))
{
       @Html.Hidden("ProductID", item.ProductID)
       <input type="submit" value="Delete" />
}

Se sulla pagina sono presenti molti elementi, sarà necessario racchiudere ciascuno di essi in un modulo e, di conseguenza, verranno generati molti moduli. Anche <input type = submit> rende il pulsante, non il link.
Vitaliy Markitanov

@VitaliyMarkitanov mi stai suggerendo di usare jQuery ajax?
isxaker

Guarda il mio post qui sotto in questo thread, ho spiegato la mia soluzione lì.
Vitaliy Markitanov

Nel progetto di esempio MVC, questo è più o meno esattamente quello che fanno anche loro
Maya

1

Questa è la mia soluzione al problema. Questo è il controller con 2 metodi di azione

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");
}
}

In View renderizzo il costrutto che segue la struttura.

<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 di interesse in Razor View :

  1. Funzione JavaScript confirmDelete(id)che viene chiamata quando si @Html.ActionLinkfa clic sul collegamento generato con ;

  2. confirmDelete()funzione richiesta id dell'elemento su cui si fa clic. Questo elemento viene passato dal onClickgestore confirmDelete("+feedback.Id+");return false;Prestare attenzione al gestore restituisce false per impedire l'azione predefinita, ovvero ottenere la richiesta alla destinazione. OnClickl'evento per i pulsanti potrebbe essere allegato con jQuery per tutti i pulsanti nell'elenco in alternativa (probabilmente sarà anche meglio, poiché sarà meno testo nella pagina HTML ei dati potrebbero essere passati tramite data-attributo).

  3. Il modulo ha id=myForm, per trovarlo in confirmDelete().

  4. La forma include @Html.HttpMethodOverride(HttpVerbs.Delete)per utilizzare il HttpDeleteverbo, come azione contrassegnata con il HttpDeleteAttribute.

  5. Nella funzione JS utilizzo la conferma dell'azione (con l'aiuto di plugin esterni, ma anche la conferma standard funziona bene. Non dimenticare di usare bind()in call back o var that=this(come preferisci).

  6. La forma ha un elemento nascosto con id='idField'e name='id'. Quindi, prima che il modulo venga inviato dopo la conferma ( result==true), il valore dell'elemento nascosto viene impostato sul valore passato argomento e il browser invierà i dati al controller in questo modo:

URL richiesta :http://localhost:38874/Feedback/Delete

Metodo di richiesta : Codice di stato POST: 302 Trovato

Intestazioni di risposta

Posizione: / Feedback Host: localhost: 38874 Form Data X-HTTP-Method-Override: DELETE id: 5

Come puoi vedere, è una richiesta POST con X-HTTP-Method-Override: DELETE e dati nel corpo impostati su "id: 5". La risposta ha un codice 302 che reindirizza all'azione Indice, in questo modo aggiorni lo schermo dopo l'eliminazione.


0

Consiglierei di rimanere puri sui principi REST e di utilizzare un'eliminazione HTTP per le tue eliminazioni. Purtroppo le specifiche HTML hanno solo HTTP Get & Post. Un tag può solo un HTTP Get. Un tag del modulo può eseguire un'operazione HTTP Get o Post. Fortunatamente se usi ajax puoi fare una cancellazione HTTP e questo è quello che consiglio. Vedere il seguente post per i dettagli: Http Deletes


0

La chiamata a $ .post () non funzionerà poiché è basata su Ajax. Quindi a questo scopo deve essere utilizzato un metodo ibrido.

Di seguito è la soluzione che funziona per me.

Passaggi: 1. Crea un URL per href che chiama il metodo a con url e parametro 2. Chiama il normale POST usando il metodo JavaScript

Soluzione:

In .cshtml:

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

Nota: il metodo anonimo dovrebbe essere racchiuso in (....) () ie

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

postGo è definito come di seguito in JavaScript. Il riposo è semplice ..

@ Url.Action ("View") crea l'URL per la chiamata

{'id': @ reception.ReceiptId} crea parametri come oggetto che a sua volta viene convertito in campi POST nel metodo postGo. Questo può essere qualsiasi parametro richiesto

In 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 di riferimento che ho usato per postGo

GET / POST non ajax utilizzando jQuery (plugin?)

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


0

jQuery.post()funzionerà se disponi di dati personalizzati. Se vuoi pubblicare un modulo esistente, è più facile da usare ajaxSubmit().

E non è necessario impostare questo codice in ActionLinkse stesso, poiché è possibile allegare il gestore dei collegamenti document.ready()all'evento (che è comunque un metodo preferito), ad esempio utilizzando il $(function(){ ... })trucco jQuery.


0

Mi sono imbattuto in questa necessità di POST da una pagina di ricerca (indice) alla pagina dei risultati. Non avevo bisogno di quanto @Vitaliy ha dichiarato, ma mi ha indirizzato nella giusta direzione. Tutto quello che dovevo fare era questo:

@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>
}

Il mio controller aveva il seguente metodo di firma:

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

0

Questo è tratto dal progetto di esempio 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>
            }
        }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.