Перенаправление на действие и необходимость передачи данных
У меня есть контроллер, который обрабатывает три действия, характерные для моей проблемы.
Первое - это действие редактирования, которое возвращает представление с формой HTML, которое пользователь может редактировать свойства для данного элемента.
Второе - это действие обновления, которое принимает сообщение назад в браузере и обновляет базу данных. Когда обновление выполнено успешно, мы делаем перенаправление на действие.
Третий - это действие шоу, которое показывает детали данного элемента. Это действие происходит там, где мы перенаправляемся после успешного обновления.
Поток:
Показать → Изменить → Обновить (Sucess: y → перенаправить на Show, n → return Edit)
Я хочу добиться того, чтобы флаг был сработал, когда обновление было успешным, так что на следующем Show view я могу отобразить сообщение для пользователя. Проблема в том, что я не уверен на 100% наилучшим образом переносить эти данные по вызову RedirectToAction(). Я думал, что я использовал строку запроса? Мы уже несем переменные вокруг строки запроса для другой цели, но часть моего скептически относится к злоупотреблениям. Вызов перенаправления ниже.
RouteValueDictionary dict = Foo.GetRouteValues(bar);
RedirectToAction("Show", dict);
Я тоже прочитал этот вопрос, но я не знаю, как использовать свойство TempData, если мне это не нужно.
Question
Спасибо за некоторые предложения!
Ответы
Ответ 1
РЕДАКТИРОВАТЬ: Извините, изначально не видел вашей заметки о том, что вы не хотите использовать TempData.
Вкратце - вы хотите, чтобы ваше сообщение снова появилось, если клиент обновляет/перезагружает страницу, на которую они перенаправлены?
Если вы это сделаете, используйте кнопку querystring, например:
return(RedirectToAction("Index", new { message = "hi there!" }));
а затем либо определите
public ActionResult Index(string message) { }
или явно вытащите Request.QueryString [ "message" ] и передайте его в View через ViewData обычным способом. Это также будет работать на браузерах, которые не принимают файлы cookie с вашего сайта.
Если вы НЕ хотите, чтобы сообщение отображалось снова, ASP.NET MVC 1.0 предоставляет коллекцию TempData для этой конкретной цели.
Значения свойств TempData хранятся в состоянии сеанса до следующего запроса от того же браузера, после чего они очищаются - так что если вы поместите что-то в TempData сразу перед возвратом RedirectToAction, он будет доступен на результат перенаправления, но будет немедленно очищен.
Здесь простое изменение в HomeController в стартовом проекте ASP.NET MVC:
public ActionResult Index() {
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(string submitButton) {
TempData["message"] = "You clicked " + submitButton;
return(RedirectToAction("Index"));
}
public ActionResult About() {
return View();
}
и соответствующий вид /Views/Home/Index.aspx должен содержать примерно следующее:
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
<% if (TempData["message"] != null) { %>
<p><%= Html.Encode(TempData["message"]) %></p>
<% } %>
<% using (Html.BeginForm()) { %>
<input type="submit" name="submitButton" value="Button One" />
<input type="submit" name="submitButton" value="Button Two" />
<% } %>
</asp:Content>
Вы заметите, что сообщение TempData отображается сразу после последовательности POST-REDIRECT-GET, но если вы обновите страницу, она не будет отображаться снова.
Обратите внимание, что это изменение изменилось в ASP.NET MVC 2 - см. "Состояние передачи между методами действий" в в этой статье для получения дополнительной информации.
Ответ 2
Никогда не был поклонником TempData
и, кроме того, я не хотел передавать флаг успеха в URL-адрес, поскольку я не хотел видеть
App/Настройки? SaveSuccess = истина
в строке URL браузера.
В моем решении используется временный файл cookie:
[HttpPost]
public ActionResult Settings(SettingsViewModel view)
{
if (ModelState.IsValid)
{
//save
Response.SetCookie(new HttpCookie("SettingsSaveSuccess", ""));
return RedirectToAction("Settings");
}
else
{
return View(view);
}
}
и в соответствующей проверке действия Get для присутствия этого Cookie и удалить его:
[HttpGet]
public ActionResult Settings()
{
var view = new SettingsViewModel();
//fetch from db and do your mapping
bool saveSuccess = false;
if (Request.Cookies["SettingsSaveSuccess"] != null)
{
Response.SetCookie(new HttpCookie("SettingsSaveSuccess", "") { Expires = DateTime.Now.AddDays(-1) });
saveSuccess = true;
}
view.SaveSuccess = saveSuccess;
return View(view);
}
nb это может быть довольно скользкий наклон, если вы начинаете передавать что-либо более сложное, чем логический флаг