1) TempData
Umożliwia przechowywanie danych, które przetrwają dla przekierowania. Wewnętrznie używa Sesji jako magazynu kopii zapasowych, po wykonaniu przekierowania dane są automatycznie eksmitowane. Wzór jest następujący:
public ActionResult Foo()
{
// store something into the tempdata that will be available during a single redirect
TempData["foo"] = "bar";
// you should always redirect if you store something into TempData to
// a controller action that will consume this data
return RedirectToAction("bar");
}
public ActionResult Bar()
{
var foo = TempData["foo"];
...
}
2) ViewBag, ViewData
Umożliwia przechowywanie danych w akcji kontrolera, która zostanie użyta w odpowiednim widoku. Zakłada się, że akcja zwraca widok i nie przekierowuje. Mieszka tylko podczas bieżącego żądania.
Wzór jest następujący:
public ActionResult Foo()
{
ViewBag.Foo = "bar";
return View();
}
i w widoku:
@ViewBag.Foo
lub z ViewData:
public ActionResult Foo()
{
ViewData["Foo"] = "bar";
return View();
}
i w widoku:
@ViewData["Foo"]
ViewBag
jest tylko dynamicznym opakowaniem ViewData
i istnieje tylko w ASP.NET MVC 3.
To powiedziawszy, żaden z tych dwóch konstruktów nigdy nie powinien być używany. Powinieneś używać modeli widoków i silnie typowanych widoków. Prawidłowy wzorzec jest następujący:
Zobacz model:
public class MyViewModel
{
public string Foo { get; set; }
}
Akcja:
public Action Foo()
{
var model = new MyViewModel { Foo = "bar" };
return View(model);
}
Mocno napisany widok:
@model MyViewModel
@Model.Foo
Po tym krótkim wstępie odpowiedzmy na twoje pytanie:
Moje wymaganie polega na tym, że chcę ustawić wartość w kontrolerze, który przekieruje do ControllerTwo, a Controller2 wyświetli widok.
public class OneController: Controller
{
public ActionResult Index()
{
TempData["foo"] = "bar";
return RedirectToAction("index", "two");
}
}
public class TwoController: Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
Foo = TempData["foo"] as string
};
return View(model);
}
}
i odpowiedni widok ( ~/Views/Two/Index.cshtml
):
@model MyViewModel
@Html.DisplayFor(x => x.Foo)
Istnieją także wady stosowania TempData: jeśli użytkownik naciśnie F5 na stronie docelowej, dane zostaną utracone.
Osobiście nie używam TempData. To dlatego, że wewnętrznie korzysta z sesji, a ja wyłączam sesję w moich aplikacjach. Wolę bardziej RESZTNY sposób na osiągnięcie tego. To jest: w pierwszej akcji kontrolera, która wykonuje przekierowanie, zapisz obiekt w magazynie danych i użyj wygenerowanego unikalnego identyfikatora podczas przekierowania. Następnie w akcji docelowej użyj tego identyfikatora, aby pobrać początkowo przechowywany obiekt:
public class OneController: Controller
{
public ActionResult Index()
{
var id = Repository.SaveData("foo");
return RedirectToAction("index", "two", new { id = id });
}
}
public class TwoController: Controller
{
public ActionResult Index(string id)
{
var model = new MyViewModel
{
Foo = Repository.GetData(id)
};
return View(model);
}
}
Widok pozostaje taki sam.