2011-01-13 38 views
3

我想使用TempData在Post和後續重定向之間存儲消息,但是TempData始終爲空。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 Web服務器上進行測試。沒有Ajax調用,我從主頁面中刪除了所有的Html.RenderAction調用。我可以看到TempData在GetAuditedMessages中每次請求只訪問一次,並且只在OnResultExecuting中存儲一次。沒有什麼會覆蓋數據。會話狀態是允許的。

該代碼有點簡化。我們還使用防僞令牌,自定義過濾器進行授權和動作選擇,但不應影響TempData行爲。

我不明白。我在測試應用程序之前使用了TempData,它工作正常。

+0

我在維護一些代碼,可能已經從您的問題中複製和粘貼,並且TempData總是回來空的.. arg。 – 2011-08-15 22:39:08

回答

9

我在代碼中看到的問題是,您試圖從控制器構造函數中的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; 
    } 
} 
+0

我沒有測試它,因爲我已經無法訪問該代碼,但是您的解釋看起來是正確的,因爲`TempData`在其他情況下適用於我,我相信這是有效的答案。 – 2011-08-21 14:12:24

1

我覺得這是發生了什麼事:

在的CancelEdit,返回你的RedirectToAction,並且框架重定向到「詳細信息」。在你的Detail方法中,ActionExecuting觸發,但是它的filterContext.Result不是你的RedirectToAction結果 - 這是一個新的結果(實際上,目前還沒有結果)。

你需要檢查「filterContext.Result是RedirectToRouteResult」嗎?看起來您只會在執行重定向之前添加這些消息。

+0

我不這麼認爲。我確定調用順序如下:第一個請求(CancelEdit - > OnResultExecuting),第二個請求(構造函數 - > GetAuditMessages)。我也確定在CancelEdit之後,它滿足了RedirectToAction類型的條件。 – 2011-01-13 23:09:22