ViewBag,ViewData和TempData


209

任何人都可以解释何时使用

  1. 临时数据
  2. ViewBag
  3. ViewData

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

我尝试使用ViewBag,当我到达第二个控制器时,该值会丢失。

我可以知道何时使用以及优缺点吗?

谢谢


5
是一篇很棒的文章,解释了这些差异。
Beku

1
stackoverflow.com/a/17199709/2015869
Imad Alazani 2013年

Answers:


293

1)温度数据

允许您存储将保留重定向的数据。在内部,它使用会话作为后备存储,在进行重定向后,数据将自动逐出。模式如下:

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

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

模式如下:

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

简短介绍之后,让我们回答您的问题:

我的要求是我想在一个控制器中设置一个值,该控制器将重定向到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。这是因为在内部它使用会话,并且我在应用程序中禁用了会话。我更喜欢一种RESTful的方式来实现这一目标。这是:在执行重定向的第一个控制器操作中,将对象存储在数据存储中,并在重定向时使用用户生成的唯一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);
    }
}

视图保持不变。


57
很好的答案,但我不同意教条式的陈述:“这两种结构都不应该使用”。我发现ViewBag有几个合法用法。例如,我ViewBag.Title在所有视图中设置了一个属性,该属性将在_Layout.cshtml基本视图文件中使用。我使用它的另一种情况是向用户提供信息消息(例如“产品保存成功!”)。我放置了一些通用标记Layout.cshtml来呈现消息(如果提供),这使我可以设置ViewBag.Message任何Action。无论哪种情况,都使用ViewModel属性有太多缺点。
杰西·韦伯

22
我必须同意Jesse的观点,尽管这是一个很好的描述,但公然指出,使用ViewBag并没有充分的理由,这只是见仁见智,也不是事实。过度使用ViewBag当然是一种不好的做法,有些开发人员会陷入这种陷阱,但是高雅地使用它是一种强大的资源。
罗恩·德弗雷塔斯

1
@ ron.defreitas,好的,然后告诉我,为什么要使用ViewBag。请描述ViewBag可以使用的一种特定的现实情况。既然您说的是这样,我引用了一个强大的资源,所以我猜您在某些特定情况下该强大的资源强大的。由于我从未在职业生涯中使用过它,因此我很高兴学习人们如何使用这种强大的武器。
Darin Dimitrov

27
我们这里有一位精英人士。杰西·达林(Darin,Jesse)特别提到了这样一个例子。仅仅因为总是有其他的做事方法并不能自动否定它们的用处。
Djentleman

2
@DarinDimitrov:我现在有一个场景,我需要从属性方法中向视图传递一些信息。使用filterContext.Controller.ViewData比尝试将其传递给强类型的视图要容易得多。就是说,谢谢您的解释,它非常有用。
安迪

15

ASP.NET MVC为我们提供了三个选项ViewData,ViewBag和TempData,用于将数据从控制器传递到视图并在下一个请求中传递。ViewData和ViewBag几乎相似,而TempData承担其他责任。让我们讨论或获取关于这三个对象的关键点:

ViewBag和ViewData之间的相似之处:

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

ViewBag和ViewData之间的区别:

  • ViewData是对象的字典,该对象派生自ViewDataDictionary类,并且可以使用字符串作为键进行访问。
  • ViewBag是一个动态属性,它利用了C#4.0中的新动态功能。
  • ViewData需要对复杂的数据类型进行类型转换,并检查是否为空值以避免错误。
  • ViewBag不需要复杂数据类型的类型转换。

ViewBag和ViewData示例:

public ActionResult Index()
{
    ViewBag.Name = "Monjurul Habib";
    return View();
}


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

在视图中:

@ViewBag.Name 
@ViewData["Name"] 

TempData:

TempData还是从TempDataDictionary类派生的字典,并存储在短期会话中,它是一个字符串键和对象值。区别在于对象的生命周期。TempData在HTTP请求时保留该信息。这意味着仅从一页到另一页。这也适用于302/303重定向,因为它位于同一HTTP请求中。当您从一个控制器移至另一控制器或从一个动作移至另一动作时,有助于维护数据。换句话说,当您重定向时,“ TempData”有助于在这些重定向之间维护数据。它在内部使用会话变量。当前和后续请求中使用临时数据仅表示当您确定下一个请求将重定向到下一个视图时才使用。对于复杂的数据类型,它需要进行类型转换,并检查是否为空值以避免错误。

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

最后一种机制是Session,它的工作方式类似于ViewData,就像Dictionary一样,它使用字符串作为键,而对象则作为值。这一个存储在客户端Cookie中,可以使用更长的时间。它还需要更多的验证,才能永远不拥有任何机密信息。关于ViewData或ViewBag,您应该明智地使用它来提高应用程序性能。因为每个动作都要经过常规asp.net mvc请求的整个生命周期。您可以在子操作中使用ViewData / ViewBag,但请注意不要使用它来填充可能污染控制器的无关数据。


11

临时数据

基本上就像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

数据将保留到相应的视图


4

Asp.Net MVC中的TempData是非常有用的功能之一。它用于将数据从当前请求传递到后续请求。换句话说,如果我们希望在发生重定向时将数据从一页发送到另一页,则可以使用TempData,但是需要在代码中做一些考虑才能在MVC中实现此功能。因为TempData的寿命很短,并且仅在目标视图完全加载后才存在。但是,我们可以使用Keep()方法将数据持久存储在TempData中。

阅读更多


3

MVC中的ViewBag,ViewData,TempData和View状态

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是对象的字典,该对象派生自ViewDataDictionary类,并且可以使用字符串作为键进行访问。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(); 
}

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

1
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
    } 

1

TempData在首次读取之前将一直可用,一旦您读取它,它将不再可用,这对于传递快速消息以查看在首次读取后将消失的信息很有用。ViewBag在将数据快速传递到视图时更有用,通常应该通过模型将所有数据传递到视图,但是在某些情况下,当模型直接从映射到数据库的类(例如实体框架)传递给视图时,无需更改模型以传递新的数据,就可以将其粘贴到视图包中。ViewData只是ViewBag的索引版本,在MVC3之前使用


0

此外,viewbag和temptdata的范围也不同。viewbag基于第一视图(在操作方法之间不共享),但是temptdata可以在操作方法之间相互共享。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.