3

Post とその後のリダイレクトの間でメッセージを保存するために TempData を使用したいのですが、TempData は常に空です。

TempData を渡すためのインフラストラクチャを提供する BaseContoller があります。単純化されたコードは次のようになります。

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 開発 Web サーバーでテストされます。Ajax 呼び出しはなく、マスター ページからすべての Html.RenderAction 呼び出しを削除しました。TempData は、GetAuditedMessages で要求ごとに 1 回だけアクセスされ、OnResultExecuting で 1 回だけ保存されることがわかります。データを上書きするものはありません。セッション状態は許可されています。

コードは少し単純化されています。また、偽造防止トークン、承認およびアクション選択用のカスタム フィルターも使用していますが、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 メソッドでは、ActionExecuting が起動しますが、filterContext.Result は RedirectToAction の結果ではありません。これは新しい結果です (実際には、まだ結果はありません)。

「filterContext.Result is RedirectToRouteResult」のチェックが必要ですか? リダイレクトを実行する前に、これらのメッセージのみが追加されるようです。

于 2011-01-13T20:00:57.517 に答える