Як перенаправляти на сторінку за допомогою дієслова 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.