Як перенаправляти на сторінку за допомогою дієслова POST?


131

Коли ви телефонуєте RedirectToAction в контролер, він автоматично переспрямовується за допомогою HTTP GET. Як я можу сказати, щоб вона використовувала HTTP POST?

У мене є дія, яка приймає як GET, так і POST-запити, і я хочу мати можливість RedirectToActionвикористовувати POST та надсилати йому деякі значення.

Подобається це:

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

Я хочу, щоб значення someValueта anotherValueзначення надсилалися за допомогою HTTP POST замість GET. Хтось знає, як це зробити?


Публікація відповідей від Jason буде працювати в більшості сценаріїв, єдина проблема, яку я бачу, це те, що це схильність до аварій. тобто виклик методу дії безпосередньо обходить усі фільтри, застосовані до дії. Так, у випадку, якщо до методу дії застосовано якийсь фільтр аутентифікації або фільтр, застосований до цього, ці дані можуть бути втрачені. Виклик методу дії безпосередньо буде працювати, але його слід ретельно застосовувати.
amarnath chatterjee

Відповіді:


103

HTTP не підтримує перенаправлення на сторінку за допомогою POST. Коли ви кудись переспрямовуєтесь, заголовок HTTP "Місцезнаходження" повідомляє веб-переглядачу, куди йти, і браузер робить GET-запит на цю сторінку. Вам, мабуть, доведеться просто написати код вашої сторінки, щоб прийняти GET-запити, а також POST-запити.


4
Цікаво, чому моя відповідь не прийнята, я вважаю, що моя риторика є здоровою. :) Знову ж таки, я, можливо, буду трохи упереджений щодо цього ...
Джейсон Бантінг

14
Хоча ця відповідь в основному правильна, вона не є повною. Дивіться відповідь Джейсона Бантінга нижче для набагато кращого вирішення.
Адріан Григоре

160

Для вашого конкретного прикладу я б просто зробив це, оскільки вам, очевидно, не важливо, щоб браузер фактично отримав переспрямування (в силу прийняття відповіді, яку ви вже прийняли):

[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();
}

Це працює легко, і насправді немає ніякого смішного бізнесу - це дозволяє зберегти той факт, що другий дійсно приймає лише HTTP POST-запити (за винятком цього випадку, який у будь-якому випадку під вашим контролем), і вам не потрібно використовуйте або TempData, про що говорить посилання, яке ви розмістили у своїй відповіді.

Я хотів би знати, що з цим "не так", якщо є щось. Очевидно, що якщо ви дійсно надіслали до браузера переадресацію, це не спрацює, але тоді ви повинні запитати, чому ви намагаєтеся конвертувати це незалежно, оскільки мені це здається дивним.

Сподіваюся, що це допомагає.


7
Хто знає, чому вас зневажали. Це дуже корисний метод.
Пітер Дж

2
Ось так я завжди вирішував цю проблему. Відмовлятися від цього немає сенсу.
Адріан Григоре

39
Я проголосував, хоча я не згоден називати людей ідіотами, коли ви їх не знаєте.
Джим Шуберт

3
Я не прихильник, але я обережна з цим, якщо ви повинні викликати представлення з іншою назвою, або якщо параметри важливі, вони втрачаються. Причина полягає в тому, що URL-адреса відображатиме параметри дії + перед переадресацією на сторону сервера. Це може призвести до плутання користувача, особливо якщо він оновив сторінку, а потім опинився на попередній сторінці (тому що для оновлення використовувався старий URL). Ця методика дуже схожа на сервер asp.net's Server.Transfer, і слід виконувати ті ж застереження.
AaronLS

15
Я не виступав проти цього, але я можу бачити причину. Цей метод порушує умову кодування, встановлену за схемою MVC. Він працює лише при виклику однієї дії. Якщо дія інша, навіть на тому ж контролері, значення маршрутизації прикручуються, і неправильний вигляд повертається. Коротше кажучи: не робіть цього.
erlando

21

Якщо ви хочете передавати дані між двома діями під час переадресації без включення будь-яких даних у рядок запиту, поставте модель в об’єкт TempData.

ДІЯ

TempData["datacontainer"] = modelData;

ПОГЛЯД

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

TempData призначений для дуже короткочасного екземпляра, і використовувати його слід лише під час поточних та наступних запитів! Оскільки TempData працює таким чином, вам потрібно точно знати, яким буде наступний запит, і перенаправлення на інший вид - це єдиний раз, коли ви можете це гарантувати.

Тому єдиний сценарій, коли використання TempData надійно працюватиме, це коли ви переспрямовуєтесь.


11

спробуйте це

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
Ненавиджу, але люблю :)
divinci

Такий злом, але це був єдиний спосіб, коли я міг робити те, що хотів, не порушуючи DRY і не переробляючи всю свою установку! Дякую!
jamheadart

6

Я хотів би розширити відповідь Джейсона Бантінга

подобається це

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

І Елі буде тут для чогось ідеї про те, як зробити її загальною змінною

Може отримати всі типи контролера


Не слід створювати екземпляр до контролера, new ...()оскільки ви втратите RequestContext- якщо ви вже в тому ж контролері, вам може не знадобитися створювати новий екземпляр. В іншому випадку прийміть такий спосіб: SampelController sampleController = DependencyResolver.Current.GetService<SampelController>()тоді: sampleController.ControllerContext = new ControllerContext(Request.RequestContext, sampleController);тоді ви можете return sampleController.Index(2, "text");лише натякнути :)
Маттіас Бургер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.