Slee
Slee

Reputation: 28248

add to TempData from non controller class

How do I add to the TempData dictionary from a non controller class?

Upvotes: 4

Views: 10571

Answers (4)

Alex
Alex

Reputation: 14503

You do not need the ControllerContext, you only need the current HttpContext.

And you do not need to pass anything, you can create a new SessionStateTempDataProvider and use this, because the only thing the SaveTempData-method of this class is doing is setting a IDictionary on a specific key in the current session.

(If your application is not using any custom ITempDataProvider. If you do, you obviously have to rely on that instead.)

The SessionStateTempDataProvider is a very simple class:

// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.

using System.Collections.Generic;
using System.Web.Mvc.Properties;

namespace System.Web.Mvc
{
    public class SessionStateTempDataProvider : ITempDataProvider
    {
        internal const string TempDataSessionStateKey = "__ControllerTempData";

        public virtual IDictionary<string, object> LoadTempData(ControllerContext controllerContext)
        {
            HttpSessionStateBase session = controllerContext.HttpContext.Session;

            if (session != null)
            {
                Dictionary<string, object> tempDataDictionary = session[TempDataSessionStateKey] as Dictionary<string, object>;

                if (tempDataDictionary != null)
                {
                    // If we got it from Session, remove it so that no other request gets it
                    session.Remove(TempDataSessionStateKey);
                    return tempDataDictionary;
                }
            }

            return new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
        }

        public virtual void SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }

            HttpSessionStateBase session = controllerContext.HttpContext.Session;
            bool isDirty = (values != null && values.Count > 0);

            if (session == null)
            {
                if (isDirty)
                {
                    throw new InvalidOperationException(MvcResources.SessionStateTempDataProvider_SessionStateDisabled);
                }
            }
            else
            {
                if (isDirty)
                {
                    session[TempDataSessionStateKey] = values;
                }
                else
                {
                    // Since the default implementation of Remove() (from SessionStateItemCollection) dirties the
                    // collection, we shouldn't call it unless we really do need to remove the existing key.
                    if (session[TempDataSessionStateKey] != null)
                    {
                        session.Remove(TempDataSessionStateKey);
                    }
                }
            }
        }
    }
}

Thus we can do:

var httpContext = new HttpContextWrapper(HttpContext.Current);
var newValues = new Dictionary<string, object> {{"myKey", myValue}};
new SessionStateTempDataProvider().SaveTempData(new ControllerContext { HttpContext = httpContext }, newValues);

Note that this is overriding the existing Dictionary every time, so if you want to add data sequentially, you obviously have to rely on an intermediate container or write some extra logic to merge the existing values with the new values.

My case where I need to do this is for error page handling, where I do redirect, but where I need to to have the logic of persisting temporary data outside of the scope of the controller.

Upvotes: 4

Jaykishan
Jaykishan

Reputation: 81

ControllerBase.TempData Property

System.Web.Mvc.TempDataDictionary

You can use public TempDataDictionary TempData { get; set; }

to use TempData

e.g. Like TempData.Clear(); // Clear TempData in other class

Upvotes: 1

liammclennan
liammclennan

Reputation: 5368

You would have to pass the TempDataDictionary to the other class. I do this quite a bit and there is nothing wrong with it as long the other class is related to presentation (which it sounds like it is).

Upvotes: 4

Kyle West
Kyle West

Reputation: 9108

To do so you'd need the current controller context, otherwise you cannot.

ViewContext.Controller.TempData["whatever"] = whatever

Upvotes: 0

Related Questions