谁能解释一下,什么时候用

TempData ViewBag ViewData

我有一个要求,我需要在控制器1中设置一个值,控制器将重定向到控制器2,控制器2将呈现视图。

我尝试过使用ViewBag,当我到达控制器2时,值就丢失了。

我能知道什么时候使用和优缺点吗?

谢谢


当前回答

1) TempData

允许您存储重定向时仍能保存的数据。在内部,它使用会话作为备份存储,重定向后,数据被自动清除。模式如下:

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)视图包,视图数据

允许您在控制器动作中存储数据,这些数据将在相应的视图中使用。这假设操作返回一个视图,并且不重定向。仅在当前请求期间存活。

模式如下:

public ActionResult Foo()
{
    ViewBag.Foo = "bar";
    return View();
}

在视图中:

@ViewBag.Foo

或使用ViewData:

public ActionResult Foo()
{
    ViewData["Foo"] = "bar";
    return View();
}

在视图中:

@ViewData["Foo"]

ViewBag只是一个围绕ViewData的动态包装,只存在于ASP中。Net MVC 3。

也就是说,这两种结构都不应该被使用。您应该使用视图模型和强类型视图。正确的模式是这样的:

视图模型:

public class MyViewModel
{
    public string Foo { get; set; }
}

行动:

public Action Foo()
{
    var model = new MyViewModel { Foo = "bar" };
    return View(model);
}

强类型视图:

@model MyViewModel
@Model.Foo

简单介绍之后,让我们来回答你的问题:

我的要求是在控制器1中设置一个值 controller将重定向到ControllerTwo, Controller2将呈现 视图。

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);
    }
}

和对应的视图(~/Views/Two/Index.cshtml):

@model MyViewModel
@Html.DisplayFor(x => x.Foo)

使用TempData也有缺点:如果用户在目标页面上按F5,数据就会丢失。

我个人也不使用TempData。这是因为它内部使用会话,我禁用会话在我的应用程序。我更喜欢用一种更舒适的方式来实现这一点。即:在执行重定向的第一个控制器操作中,将对象存储在数据存储中,并在重定向时使用生成的唯一id。然后在目标操作上使用这个id来取回初始存储的对象:

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);
    }
}

视图保持不变。

其他回答

1) TempData

允许您存储重定向时仍能保存的数据。在内部,它使用会话作为备份存储,重定向后,数据被自动清除。模式如下:

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)视图包,视图数据

允许您在控制器动作中存储数据,这些数据将在相应的视图中使用。这假设操作返回一个视图,并且不重定向。仅在当前请求期间存活。

模式如下:

public ActionResult Foo()
{
    ViewBag.Foo = "bar";
    return View();
}

在视图中:

@ViewBag.Foo

或使用ViewData:

public ActionResult Foo()
{
    ViewData["Foo"] = "bar";
    return View();
}

在视图中:

@ViewData["Foo"]

ViewBag只是一个围绕ViewData的动态包装,只存在于ASP中。Net MVC 3。

也就是说,这两种结构都不应该被使用。您应该使用视图模型和强类型视图。正确的模式是这样的:

视图模型:

public class MyViewModel
{
    public string Foo { get; set; }
}

行动:

public Action Foo()
{
    var model = new MyViewModel { Foo = "bar" };
    return View(model);
}

强类型视图:

@model MyViewModel
@Model.Foo

简单介绍之后,让我们来回答你的问题:

我的要求是在控制器1中设置一个值 controller将重定向到ControllerTwo, Controller2将呈现 视图。

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);
    }
}

和对应的视图(~/Views/Two/Index.cshtml):

@model MyViewModel
@Html.DisplayFor(x => x.Foo)

使用TempData也有缺点:如果用户在目标页面上按F5,数据就会丢失。

我个人也不使用TempData。这是因为它内部使用会话,我禁用会话在我的应用程序。我更喜欢用一种更舒适的方式来实现这一点。即:在执行重定向的第一个控制器操作中,将对象存储在数据存储中,并在重定向时使用生成的唯一id。然后在目标操作上使用这个id来取回初始存储的对象:

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);
    }
}

视图保持不变。

TempData

基本上它就像一个DataReader,一旦读取,数据就会丢失。

查看这个视频

例子

public class HomeController : Controller
{
    public ActionResult Index()
    {
        ViewBag.Message = "Welcome to ASP.NET MVC!";
        TempData["T"] = "T";
        return RedirectToAction("About");
    }

    public ActionResult About()
    {
        return RedirectToAction("Test1");
    }

    public ActionResult Test1()
    {
        String str = TempData["T"]; //Output - T
        return View();
    }
}

如果你注意上面的代码,在TempData被读取之前,RedirectToAction对TempData没有影响。因此,一旦TempData被读取,值就会丢失。

如何在阅读后保存TempData ?

检查动作方法测试1和测试2中的输出

public class HomeController : Controller
{
    public ActionResult Index()
    {
        ViewBag.Message = "Welcome to ASP.NET MVC!";
        TempData["T"] = "T";
        return RedirectToAction("About");
    }

    public ActionResult About()
    {
        return RedirectToAction("Test1");
    }

    public ActionResult Test1()
    {
        string Str = Convert.ToString(TempData["T"]);
        TempData.Keep(); // Keep TempData
        return RedirectToAction("Test2");
    }

    public ActionResult Test2()
    {
        string Str = Convert.ToString(TempData["T"]); //OutPut - T
        return View();
    }
}

如果你注意上面的代码,在RedirectToAction和读取数据之后,数据不会丢失,原因是,我们使用的是TempData.Keep()。是,

通过这种方式,你也可以让它在其他控制器中保持多长时间。

ViewBag / ViewData

数据将持久化到相应的视图

而且viewbag和temptdata的作用域是不同的。Viewbag是基于第一个视图(不是在动作方法之间共享),但是temptdata可以在一个动作方法之间共享。

TempData will be always available until first read, once you read it its not available any more can be useful to pass quick message also to view that will be gone after first read. ViewBag Its more useful when passing quickly piece of data to the view, normally you should pass all data to the view through model , but there is cases when you model coming direct from class that is map into database like entity framework in that case you don't what to change you model to pass a new piece of data, you can stick that into the viewbag ViewData is just indexed version of ViewBag and was used before MVC3

void Keep()

Calling this method with in the current action ensures that all the items in TempData are not removed at the end of the current request.

    @model MyProject.Models.EmpModel;
    @{
    Layout = "~/Views/Shared/_Layout.cshtml";
    ViewBag.Title = "About";
    var tempDataEmployeet = TempData["emp"] as Employee; //need typcasting
    TempData.Keep(); // retains all strings values
    } 

void Keep(string key)

Calling this method with in the current action ensures that specific item in TempData is not removed at the end of the current request.

    @model MyProject.Models.EmpModel;
    @{
    Layout = "~/Views/Shared/_Layout.cshtml";
    ViewBag.Title = "About";
    var tempDataEmployeet = TempData["emp"] as Employee; //need typcasting
    TempData.Keep("emp"); // retains only "emp" string values
    }