Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

add to TempData from non controller class

Tags:

asp.net-mvc

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

like image 326
Slee Avatar asked Mar 01 '23 01:03

Slee


2 Answers

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).

like image 91
liammclennan Avatar answered Mar 07 '23 12:03

liammclennan


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.

like image 44
Alex Avatar answered Mar 07 '23 11:03

Alex