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, когда форма действительна и данные хранятся?
Ответы
Ответ 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 здесь:
Автоматическая проверка состояния модели