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

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

视图保持不变。


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

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


MVC中的ViewBag, ViewData, TempData和viewstate

http://royalarun.blogspot.in/2013/08/viewbag-viewdata-tempdata-and-view.html

ASP。NET MVC为我们提供了ViewData, VieBag和TempData三个选项,用于从控制器传递数据到视图和在下一个请求中。ViewData和ViewBag几乎是相似的,TempData执行额外的职责。

ViewBag和ViewData的相似之处:

当您从控制器移动到视图时,有助于维护数据。用于 将数据从控制器传递到相应的视图。短寿命意味着 值在重定向发生时变为空。这是因为他们的目标 是提供一种在控制器和视图之间通信的方法。这是 服务器调用中的通信机制。

ViewBag和ViewData的区别:

ViewData是派生自的对象字典 viewdatdictionary类,并使用字符串作为键访问。ViewBag 动态属性是否利用了新的动态特性 在c# 4.0。ViewData需要对复杂的数据类型进行类型转换 检查空值以避免错误。ViewBag不需要 复杂数据类型的类型转换。

ViewBag & ViewData示例:

public ActionResult Index()

{  
    ViewBag.Name = "Arun Prakash";
    return View();    
}

public ActionResult Index()  
{
    ViewData["Name"] = "Arun Prakash";
    return View(); 
}

在视图中,我们调用如下:

@ViewBag.Name   
@ViewData["Name"]

TempData:

当您从一个控制器移动到另一个控制器时,有助于维护数据 控制器或从一个动作到另一个动作。换句话说,当你 “Tempdata”帮助维护这些重定向之间的数据。 它在内部使用会话变量。TempData是一个非常 短命实例,您应该只在当前期间使用它 以及后续的请求

使用TempData可靠工作的唯一场景是重定向。这是因为重定向杀死了当前的请求(并将HTTP状态代码302 Object Moved发送到客户端),然后在服务器上创建一个新请求来服务重定向视图。

它需要对复杂的数据类型进行类型转换,并检查空值以避免错误。

public ActionResult Index()
{   
   var model = new Review()  
   {  
      Body = "Start",  
      Rating=5  
   };  

    TempData["ModelName"] = model;    
    return RedirectToAction("About");   
} 

public ActionResult About()       
{  
    var model= TempData["ModelName"];  
    return View(model);   
}  

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
    } 

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


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