2011-01-13 15 views
3

Ich möchte TempData verwenden, um Nachrichten zwischen Post und Followed Redirect zu speichern, aber TempData sind immer leer.TempData sind immer leer

Ich habe BaseContoller bietet einige Infrastruktur für die Weitergabe von TempData. Vereinfachtes Code wie folgt aussieht:

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

Aktion Methode wie folgt aussieht:

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

Anwendung auf VS-Entwicklung Web-Server getestet. Es gibt keine Ajax-Aufrufe und ich habe alle Html.RenderAction-Aufrufe von meiner Masterseite entfernt. Ich kann sehen, dass auf TempData nur einmal pro Anfrage in GetAuditedMessages zugegriffen und nur einmal in OnResultExecuting gespeichert wird. Nichts überschreibt die Daten. Der Sitzungsstatus ist erlaubt.

Der Code ist ein wenig vereinfacht. Wir verwenden auch ein Anti-Roger-Token, benutzerdefinierte Filter für die Autorisierung und für die Auswahl von Aktionen, aber es sollte das Verhalten von TempData nicht beeinflussen.

Ich verstehe es nicht. Ich habe TempData zuvor in der Testanwendung verwendet und es hat gut funktioniert.

+0

Ich behalte Code, der von Ihrer Frage kopiert und eingefügt werden konnte, und TempData wird immer leer zurückkommen. Arg. –

Antwort

9

Das Problem, das ich in Ihrem Code sehe, ist, dass Sie versuchen, die Daten aus TempData im Konstruktor des Controllers abzurufen - das ist, bevor es verfügbar ist.

Verschieben Sie den Aufruf an GetAuditMessages() in eine OnActionExecuting-Methode, und auf es wird zugegriffen.

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

Ich habe es nicht getestet, weil ich bereits keinen Zugriff auf diesen Code habe, aber Ihre Erklärung sieht korrekt aus und weil 'TempData' für mich in anderen Situationen funktioniert, glaube ich, dass es eine gültige Antwort ist. –

1

Ich denke, das ist, was passiert:

In CancelEdit wird Ihre RedirectToAction zurückgekehrt, und der Rahmen wird umgelenkt auf "Detail". In Ihrer Detail-Methode wird die ActionExecuting ausgelöst, aber es ist filterContext.Result ist nicht Ihr RedirectToAction-Ergebnis - es ist ein neues Ergebnis (eigentlich noch kein Ergebnis).

Benötigen Sie die Überprüfung für "filterContext.Result ist RedirectToRouteResult"? Es scheint, dass Sie nur diese Nachrichten hinzugefügt haben, bevor Sie eine Weiterleitung durchführen.

+0

Ich glaube nicht. Ich bin sicher, dass Anrufe in der folgenden Reihenfolge sind: Erste Anfrage (CancelEdit -> OnResultExecuting), zweite Anfrage (Konstruktor -> GetAuditMessages). Ich bin auch sicher, dass nach CancelEdit meine Bedingung mit RedirectToAction Typ erfüllt. –