Come si reindirizza a una pagina usando il verbo POST?


131

Quando si chiama RedirectToActionall'interno di un controller, reindirizza automaticamente utilizzando un HTTP GET. Come faccio a dirlo esplicitamente di utilizzare un POST HTTP?

Ho un'azione che accetta le richieste GET e POST e voglio essere in grado di RedirectToActionutilizzare POST e inviargli alcuni valori.

Come questo:

this.RedirectToAction(
    "actionname",
    new RouteValueDictionary(new { someValue = 2, anotherValue = "text" })
);

Voglio che i valori someValuee anotherValuevengano inviati utilizzando un HTTP POST anziché un GET. Qualcuno sa come fare questo?


La risposta inviata da Jason funzionerà nella maggior parte degli scenari, l'unico problema che vedo è che è soggetto a incidenti. cioè la chiamata di un metodo di azione ignora direttamente tutti i filtri applicati all'azione. Pertanto, nel caso in cui vi sia un'autenticazione o un contatore di filtri applicati al metodo di azione, i dati potrebbero andare persi. La chiamata diretta di un metodo di azione funzionerà, ma dovrebbe essere applicata con attenzione.
Amarnath Chatterjee,

Risposte:


103

HTTP non supporta il reindirizzamento a una pagina utilizzando POST. Quando reindirizzi da qualche parte, l'intestazione HTTP "Posizione" indica al browser dove andare e il browser invia una richiesta GET per quella pagina. Probabilmente dovrai semplicemente scrivere il codice per la tua pagina per accettare richieste GET e richieste POST.


4
Curioso perché la mia risposta non sia accettata, penso che la mia retorica sia valida. :) Di nuovo, potrei essere un po 'di parte al riguardo ...
Jason Bunting,

14
Sebbene questa risposta sia sostanzialmente corretta, non è completa. Vedi la risposta di Jason Bunting di seguito per una soluzione molto migliore.
Adrian Grigore,

160

Per il tuo esempio particolare, farei solo questo, dal momento che ovviamente non ti importa davvero che il browser ottenga comunque il reindirizzamento (in virtù dell'accettazione della risposta che hai già accettato):

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index() {
   // obviously these values might come from somewhere non-trivial
   return Index(2, "text");
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(int someValue, string anotherValue) {
   // would probably do something non-trivial here with the param values
   return View();
}

Funziona facilmente e non ci sono affari divertenti in corso - questo ti consente di mantenere il fatto che il secondo accetta davvero solo le richieste HTTP POST (tranne in questo caso, che è comunque sotto il tuo controllo) e non devi usa anche TempData, che è ciò che suggerisce il link che hai pubblicato nella tua risposta.

Mi piacerebbe sapere cosa c'è di "sbagliato" in questo, se c'è qualcosa. Ovviamente, se vuoi davvero aver inviato al browser un reindirizzamento, questo non funzionerà, ma allora dovresti chiederti perché dovresti provare a convertirlo indipendentemente, dal momento che mi sembra strano.

Spero che aiuti.


7
Chissà perché sei stato sottovalutato. Questo è un metodo molto utile
Peter J,

2
È così che ho sempre risolto anche questo problema. Downvoting questo non ha senso.
Adrian Grigore,

39
Ho votato, anche se non sono d'accordo con il chiamare le persone idioti quando non le conosci.
Jim Schubert,

3
Non sono un downvoter, ma l'unica avvertenza è che se dovessi chiamare una vista con un nome diverso o se i parametri sono importanti, andrebbero persi. Il motivo è che l'URL rifletterà i parametri action + prima del reindirizzamento lato server. Ciò può causare confusione da parte dell'utente, soprattutto se hanno aggiornato la pagina e si sono trovati in una pagina precedente (perché l'aggiornamento ha utilizzato il vecchio URL). Questa tecnica è essenzialmente molto simile al Server.Transfer di asp.net e le stesse precauzioni dovrebbero essere esercitate.
AaronLS,

15
Non ho votato di per sé, ma posso vedere la ragione. Questo metodo viola la convenzione di codifica impostata dal modello MVC. Funziona solo quando si chiama la stessa azione. Se l'azione è un'altra, anche sullo stesso controller, i valori di routing vengono avvitati e viene restituita la vista errata. In breve: non farlo.
Erlando,

21

Se si desidera passare i dati tra due azioni durante un reindirizzamento senza includere dati nella stringa di query, inserire il modello nell'oggetto TempData.

AZIONE

TempData["datacontainer"] = modelData;

VISUALIZZA

var modelData= TempData["datacontainer"] as ModelDataType; 

TempData è pensato per essere un'istanza di breve durata e dovresti usarla solo durante le richieste correnti e successive! Poiché TempData funziona in questo modo, è necessario sapere con certezza quale sarà la richiesta successiva e il reindirizzamento a un'altra vista è l'unica volta che è possibile garantirlo.

Pertanto, l'unico scenario in cui l'utilizzo di TempData funzionerà in modo affidabile è il reindirizzamento.


11

prova questo

return Content("<form action='actionname' id='frmTest' method='post'><input type='hidden' name='someValue' value='" + someValue + "' /><input type='hidden' name='anotherValue' value='" + anotherValue + "' /></form><script>document.getElementById('frmTest').submit();</script>");

2
Lo odio ma lo adoro :)
divinci il

Un tale hack ma era l'unico modo in cui potevo fare quello che volevo senza violare DRY o ricablare tutta la mia installazione! Grazie!
Jamheadart

6

Vorrei espandere la risposta di Jason Bunting

come questo

ActionResult action = new SampelController().Index(2, "text");
return action;

E Eli sarà qui per avere un'idea su come renderla variabile generica

Può ottenere tutti i tipi di controller


Non dovresti creare un'istanza per un controller new ...()perché perderai il RequestContext- se sei già nello stesso controller, potrebbe non essere necessario creare una nuova istanza. Altrimenti, prendi il seguente modo: SampelController sampleController = DependencyResolver.Current.GetService<SampelController>()allora: sampleController.ControllerContext = new ControllerContext(Request.RequestContext, sampleController);allora puoi return sampleController.Index(2, "text");solo un suggerimento :)
Matthias Burger
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.