2011-01-13 4 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 развития. Нет вызовов Ajax, и я удалил все вызовы Html.RenderAction со своей главной страницы. Я вижу, что TempData обращаются только один раз за запрос в GetAuditedMessages и сохраняются только один раз в OnResultExecuting. Ничто не перезаписывает данные. Состояние сеанса разрешено.

Код немного упрощен. Мы также используем маркер antiforgery, пользовательские фильтры для авторизации и выбора действия, но не должны влиять на поведение TempData.

Я не понимаю. Я использовал TempData раньше в тестовом приложении, и он работал нормально.

+0

Я поддерживаю код, который мог быть скопирован и вставлен из вашего вопроса, а TempData всегда возвращается пустым .. arg. –

ответ

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' работал для меня в других ситуациях, я считаю, что это правильный ответ. –

1

Я думаю, что это то, что происходит:

В CancelEdit, ваш RedirectToAction возвращается, и в рамках перенаправляет на «Деталь». В вашем методе Detail срабатывает ActionExecuting, но это filterContext.Result не является вашим результатом RedirectToAction - это новый результат (на самом деле, пока нет результата).

Вам нужна проверка на «filterContext.Result - RedirectToRouteResult»? Кажется, что вы добавите только эти сообщения, прежде чем выполнять перенаправление.

+0

Я так не думаю. Я уверен, что вызовы находятся в следующем порядке: Первый запрос (CancelEdit -> OnResultExecuting), второй запрос (конструктор -> GetAuditMessages). Я также уверен, что после CancelEdit он удовлетворяет моему состоянию с помощью типа RedirectToAction. –