3

我想使用 TempData 存储 Post 和后续重定向之间的消息,但 TempData 始终为空。

我有 BaseContoller 提供一些用于传递 TempData 的基础设施。简化的代码如下所示:

public abstract class BaseController : Controller
{
  public const string AuditMessagesKey = "AuditMessages";

  private List<InformationMessage> _informationMessages = new List<InformationMessage>();

  protected BaseController()
  {
    // I also tried this in overriden Initialize
    ViewData[AuditMessagesKey] = GetAuditMessages();
  }

  protected void AddAuditMessage(InformationMessage message)
  {
    if (message == null)
      return;

     _informationMessages.Add(message);
  }

  protected override void OnResultExecuting(ResultExecutingContext filterContext)
  {
    base.OnResultExecuting(filterContext);

    if (filterContext.Result is RedirectToRouteResult)
    {
      // I see that messages are stored into TempData
      TempData[AuditMessagesKey] = _informationMessages;
      // This also doesn't help
      // TempData.Keep(AuditMessagesKey);
    }
  }

  private ICollection<InformationMessage> GetAuditMessages()
  {
    // TempData are always empty here
    var messages = TempData[AuditMessagesKey] as List<InformationMessage>;

    if (messages == null)
    {
      messages = new List<InformationMessage>();
    }

    return messages;
  }
}

动作方法如下所示:

  [HttpPost]
  public ActionResult CancelEdit(RequestSaveModel model)
  {
    AddAuditMessage(new InformationMessage
      {
        Message = String.Format(Messages.RequestEditationCanceled, model.Title),
        Severity = MessageSeverity.Information
      });

    return RedirectToAction("Detail", new { Id = model.Id});
  }

应用程序在 VS Development Web 服务器上进行了测试。没有 Ajax 调用,我从母版页中删除了所有 Html.RenderAction 调用。我可以看到 TempData 在 GetAuditedMessages 中的每个请求仅被访问一次,并且在 OnResultExecuting 中仅存储一次。没有任何东西会覆盖数据。允许会话状态。

代码稍微简化了一点。我们还使用防伪令牌、用于授权和操作选择的自定义过滤器,但它不应影响 TempData 行为。

我不明白。我之前在测试应用程序中使用过 TempData,它运行良好。

4

3 回答 3

10

我在您的代码中看到的问题是您正试图从控制器构造函数中的 TempData 检索数据 - 这是在它可用之前。

将调用移动GetAuditMessages()到 OnActionExecuting 方法中,它将是可访问的。

public abstract class BaseController : Controller
{
  public const string AuditMessagesKey = "AuditMessages";

  private List<InformationMessage> _informationMessages = new List<InformationMessage>();

  protected BaseController()
  {
    // TempData is not available yet
  }

  protected override void OnActionExecuting(ActionExecutingContext filterContext)
  {
      ViewData[AuditMessagesKey] = GetAuditMessages();

      base.OnActionExecuting(filterContext);
  }

  protected void AddAuditMessage(InformationMessage message)
  {
    if (message == null)
      return;

     _informationMessages.Add(message);
  }

  protected override void OnResultExecuting(ResultExecutingContext filterContext)
  {
    base.OnResultExecuting(filterContext);

    if (filterContext.Result is RedirectToRouteResult)
    {
      // I see that messages are stored into TempData
      TempData[AuditMessagesKey] = _informationMessages;
      // This also doesn't help
      // TempData.Keep(AuditMessagesKey);
    }
  }

  private ICollection<InformationMessage> GetAuditMessages()
  {
    var messages = TempData[AuditMessagesKey] as List<InformationMessage>;

    if (messages == null)
    {
      messages = new List<InformationMessage>();
    }

    return messages;
  }
}
于 2011-08-16T16:19:48.847 回答
1

我认为这是正在发生的事情:

在 CancelEdit 中,您的 RedirectToAction 被返回,并且框架重定向到“Detail”。在您的 Detail 方法中,ActionExecuting 触发,但它的 filterContext.Result 不是您的 RedirectToAction 结果 - 它是一个新结果(实际上,目前还没有结果)。

你需要检查“filterContext.Result is RedirectToRouteResult”吗?在执行重定向之前,您似乎只会添加这些消息。

于 2011-01-13T20:00:57.517 回答
-1

在我的解决方案中,我忘记为我的开发删除 HttpCookies 它只适用于 Https 中的已发布站点

<httpCookies httpOnlyCookies="true" requireSSL="true"  />
于 2018-07-21T08:13:13.833 回答