【问题标题】:Using TempData with Post Redirect Get pattern将 TempData 与 Post Redirect Get 模式一起使用
【发布时间】:2019-05-21 08:57:45
【问题描述】:

有很多人主张在 .NET Core 2.2.x 中使用带有 PRG 模式的 TempData。

据我了解,这行代码是存储数据的:

 TempData["foo"] = JsonConvert.SerializeObject(model);

以下内容会重构模型,然后将其从 TempData 构造中删除:

string s = (string)TempData["Model"];
var model = JsonConvert.DeserializeObject<ModelType>(s);

因此,鉴于 TempData 的这种瞬态特性,请想象以下 PRG 构造。用户 POST 到 UserInfo 操作,该操作将模型打包到 TempData 并重定向到 UserInfo GET。 GET UserInfo 重构模型并显示视图。

[HttpPost]
public IActionResult UserInfo(DataCollectionModel model) {
    TempData["Model"] = JsonConvert.SerializeObject(model);
    return RedirectToAction("UserInfo");
}

[HttpGet]
public IActionResult UserInfo() {
    string s = (string)TempData["Model"];
    DataCollectionModel model = JsonConvert.DeserializeObject<DataCollectionModel>(s);
    return View(model);
}

用户现在位于 /Controller/UserInfo 页面上。如果用户按 F5 刷新页面,TempData["Model"] 将不再存在,UserInfo 上的 GET 将失败。修复可能是在读取模型后将模型存储在 TempData 中,但这不会导致内存泄漏吗?

我错过了什么吗?

【问题讨论】:

  • TempData 通常用于敏感信息。 PRG 不需要。
  • @Jasen 您将使用什么方法将信息从 POST 移动到 GET? (我没有数据库,因此不能使用 ID 传递)。
  • 如果您想在第一次访问后保留数据,会话状态将是 TempData 的逻辑替代方案。
  • @DaveCluderay 该应用程序将设置在多台服务器上,因此单机会话状态将不起作用,我认为仅为 PRG 模式引入分布式缓存会有点过头了。可能会使用 cookie 或类似的东西。

标签: c# .net asp.net-core .net-core asp.net-core-2.2


【解决方案1】:

TempData 可用于存储瞬态数据。当多个请求需要数据时,它对于重定向很有用。当读取 TempDataDictionary 中的对象时,将在该请求结束时将其标记为删除。

这意味着如果你在 TempData 上放一些东西,比如

TempData["value"] = "someValueForNextRequest";

在您访问它的另一个请求时,该值将在那里,但一旦您读取它,该值将被标记为删除:

//second request, read value and is marked for deletion
object value = TempData["value"];

//third request, value is not there as it was deleted at the end of the second request
TempData["value"] == null

Peek 和 Keep 方法允许您读取值而不将其标记为删除。假设我们回到将值保存到 TempData 的第一个请求。

使用 Peek,您无需通过一次调用将其标记为删除即可获得值,请参阅 msdn

//second request, PEEK value so it is not deleted at the end of the request
object value = TempData.Peek("value");

//third request, read value and mark it for deletion
object value = TempData["value"];

使用 Keep,您可以指定要保留的标记为删除的密钥。检索对象并稍后将其从删除中保存是 2 个不同的调用。见msdn

//second request, get value marking it from deletion
object value = TempData["value"];
//later on decide to keep it
TempData.Keep("value");

//third request, read value and mark it for deletion
object value = TempData["value"];

当您总是想为另一个请求保留值时,可以使用 Peek。保留值时使用 Keep 取决于附加逻辑。

在您的 Get 操作中进行以下更改

public IActionResult UserInfo()
    {
        //The First method ,
        string s = (string)TempData.Peek("Model");

        //The Second method
        string s = (string)TempData["Model"]; 
        TempData.Keep("Model");

        if(s==null)
        {
            return View();
        }
        else
        {
            User model = JsonConvert.DeserializeObject<User>(s);
            return View(model);
        }
    }

【讨论】:

  • 我对你在最后一个代码 sn-p 中的术语感到困惑。当您说First methodSecond method 时,您的意思是这两种方法都可以吗?
  • 是的,这两种方法都可以,根据上面 Peek 和 Keep 方法的比较,在您的场景中使用第一种方法比使用第二种方法更好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-04
  • 1970-01-01
  • 2014-05-04
  • 1970-01-01
  • 2012-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多