Подтвердить что ты не робот

Post Redirect Получить в ASP.NET MVC и проверить с остальными URL-адресами

У меня есть спокойный URL-адрес для действия редактирования страницы. Это реализовано на контроллере как метод Edit, который принимает запросы GET и метод Edit, который принимает запросы POST.

Это означает, что вы можете посетить Редактировать URL-адрес и отобразить форму для GET или сохранить форму для POST.

[HttpGet]
public ActionResult Edit(int id) {
    ...
}

[HttpPost]
public ActionResult Edit(EditModel model) {
    ...
}

Образ Post-Redirect-Get (PRG) выглядит довольно черно-белым, потому что он по существу перенаправляет каждый POST обратно на действие GET. Тем не менее, мне нужно убедиться, что это правильная вещь.

Мой план заключается в том, что в действии POST, если модель действительна, я буду использовать шаблон Post-Redirect-Get, чтобы отправить пользователя в разумное место (возможно, действие Index или Details).

Однако, если есть проблема проверки модели, я все же хочу просто отобразить представление. Я не хочу перенаправлять пользователя, потому что это означает наложение модели и ModelState на временные данные и перенаправление на действие GET, а затем добавление логики в действие GET для обработки временных данных. Я мог бы избежать всего этого, просто отображая представление.

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

Если проверка прошла, пользователь будет перенаправлен, и они будут защищены от двойных представлений.

Итак, следует ли внедрять дополнительные данные кода и данных в временные данные, чтобы строго следовать шаблону PRG, или более разумно использовать шаблон PRG, когда форма действительна и данные хранятся?

4b9b3361

Ответ 1

Вы должны сделать только перенаправление, если информация о форме действительна; в случае ошибок отправки возвратите представление из того же метода редактирования.

Выполнение этого способа соответствует PRG, потому что, если ваша модель недействительна, вы не можете вносить какие-либо изменения в состояние объектов на сервере. PRG предназначен прежде всего для предотвращения множества сообщений, которые могут непредсказуемо изменять состояние объектов сервера (например, бизнес-объектов, таблиц базы данных и т.д.); однако в вашем примере проверки пользователь может нажать "повторно отправить" столько раз, сколько захочет, и они будут всегда отправляться обратно в исходное представление с ошибками проверки - ничего на сервере не изменяется. Следовательно, вы имеете это право: только выпустите Redirect, если ваша модель проходит проверку в вашем уровне представления.

Ответ 2

Несмотря на то, что ответ Ken подчеркивает важный факт - PRG не обязательно означает "слепо возвращать перенаправление при публикации" - вы все же можете захотеть сделать перенаправление и иногда сохраняйте модельное состояние.

Самый простой способ справиться с этим сценарием - использовать фильтры действий для экспорта modelstate на сеанс (перед перенаправлением), а затем импортировать modelstate (перед выполнением нового действия). Kazi Manzur Rashid имеет несколько отличных сообщений в блоге (Часть 1 Часть 2) о лучших практиках в ASP.NET MVC. Они довольно старые, но многие советы там все еще очень применимы. Подсказка № 13 в первая статья - именно то, что вы ищете.

Ответ 3

PRG - это правильная вещь.

Вы выполняете POST для действия, и если modelstate недействителен, вы просто "экспортируете" свои данные состояния модели в переменную и перенаправляете на действие get.

Это имеет преимущество, в отличие от принятого ответа, что вам не нужно переписывать код в действии [Post], чтобы воссоздать представление.

в действии get вы загружаете ModelState, экспортированный из сообщения.

TempData - отличное место для этого, код будет примерно таким:

[HttpGet]
public ActionResult Edit(int id) {
    // import model state from tempdata
    ...
}

[HttpPost]
public ActionResult Edit(EditModel model) {
    // if modelstate is invalid
    // save modelstate in tempdata
    // redirect to Edit/{id}
    // else 
    ...
    RedirectToAction("List")
}

это можно автоматизировать с помощью AttributeFilters, там отличный пост, созданный @ben-foster здесь:

Автоматическая проверка состояния модели