I have a dictionary in a singleton class. I am saving there the pair , every time I access to that dictionary from the method that is creating the token it shows all the credentials that I've stored there.
But when I access from another class in another project of the solutions it displays the dictionary empty. Can anybody tell me why this happens?
This is the class that manage the dictionary:
public class UserAccessToken
{
public Dictionary<string, string> UserDictionary { get; set; }
private static UserAccessToken _instance;
private UserAccessToken() { }
public static UserAccessToken Instance
{
get
{
if (_instance == null)
_instance = new UserAccessToken
{
UserDictionary = new Dictionary<string, string>()
};
return _instance;
}
}
}
This is the method that insert the key,value pair in the dictionary:
public override Task TokenEndpointResponse(OAuthTokenEndpointResponseContext context)
{
var accessToken = context.AccessToken;
if (context.Properties.Dictionary.ContainsKey("userName"))
{
var username = context.Properties.Dictionary["userName"];
// If I access here multiple times the singleton works
UserAccessToken.Instance.UserDictionary[username] = accessToken;
}
return Task.FromResult<object>(null);
}
This is the method where I access the dictionary, from here I can see that it's empty:
private bool IsTokenValid(HttpContextBase httpContext)
{
var username = httpContext.User.Identity.Name;
var userTokens = UserAccessToken.Instance.UserDictionary;
var tokenToAccess = httpContext.Request.Headers["Authorization"];
tokenToAccess = tokenToAccess.Replace("Bearer ", "");
if (userTokens.ContainsKey(username))
{
var token = userTokens[username];
if (token == tokenToAccess) return true;
}
return true;
}
I already solved my problem, but I'll let my solution here in case could be useful for somebody.
The problem is that if you are running two different projects, that will mean two different process, so, what I wanted to do is pretty impossible. I used Redis for this and it is working well.
This is an example of Redis use:
public class CallManagerCache : ICallManagerMethods{
private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer
.Connect(CloudConfigurationManager.GetSetting("RedisConnectionString")));
public static ConnectionMultiplexer cacheConnection
{
get
{
return lazyConnection.Value;
}
}
/// <summary>
/// Here you save the value in cache, you get the connection, then StringSetAsync is in charge of saving the value
/// </summary>
/// <param name="name"></param>
/// <param name="template"></param>
public async Task UpdateCallInstance(int id, byte[] data, bool instanceForCallback = false, TimeSpan? timespan = null)
{
var cache = cacheConnection.GetDatabase();
await cache.StringSetAsync(instanceForCallback ? $"Call_{id}" : id.ToString(), data, timespan ?? new TimeSpan(0, 0, 15, 0));
}
/// <summary>
/// Here you get the value in cache, you get the connection, then StringGetAsync is in charge of getting the value
/// </summary>
/// <param name="name"></param>
/// <param name="template"></param>
public async Task<CallInstance> GetById(int id, bool isForCallback)
{
var cache = cacheConnection.GetDatabase();
var callInstance = new CallInstance
{
Id = id,
InstanceData = await cache.StringGetAsync(isForCallback ? $"Call_{id}" : id.ToString())
};
return callInstance;
}
}
Related
I am using cosmos DB and I have created below generic repository for CRUD operations.
public class CosmosDBRepository : ICosmosDBRepository
{
private readonly DocumentClient _client;
private readonly string DatabaseId = "FleetHub";
public CosmosDBRepository()
{
var endpoint = CloudConfigurationManager.GetSetting("CosmoDbEndpoint");
var authkey = CloudConfigurationManager.GetSetting("CosmoDbAuthKey");
try
{
if (endpoint == null || authkey == null)
{
throw new ArgumentNullException("CosmoDbEndpoint or CosmoDbAuthKey could not be found in the config file, check your settings.");
}
if (_client == null)
{
_client = new DocumentClient(new Uri(endpoint), authkey, connectionPolicy: new ConnectionPolicy { EnableEndpointDiscovery = false });
}
CreateDatabaseIfNotExistsAsync().Wait();
CreateCollectionIfNotExistsAsync().Wait();
}
catch (Exception e)
{
throw new Exception($"Initialise failed CosmoDbEndpoint {endpoint} or CosmoDbAuthKey {authkey} could not be found in the config file, check your settings. {e.Message}");
}
}
/// <summary>
///
/// </summary>
/// <param name="id"></param>
/// <param name="partitionkey"></param>
/// <returns></returns>
public async Task<T> GetItemAsync<T>(string id, string partitionkey) where T : class
{
try
{
string CollectionId = GetAttributeCosmoDbCollection<T>(typeof(T));
Document document = await _client.ReadDocumentAsync(UriFactory.CreateDocumentUri(DatabaseId, CollectionId, id), new RequestOptions { PartitionKey = new PartitionKey(partitionkey) });
return (T)(dynamic)document;
}
catch (DocumentClientException e)
{
if (e.StatusCode == System.Net.HttpStatusCode.NotFound)
{
return null;
}
else
{
throw;
}
}
}
/// <summary>
///
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public async Task<Document> CreateItemAsync<T>(T item) where T : class
{
string CollectionId = GetAttributeCosmoDbCollection<T>(typeof(T));
return await _client.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId), item);
}
public async Task<IEnumerable<T>> GetItemsAsync<T>(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByDesc, int takeCount = -1)
where T : class
{
string CollectionId = GetAttributeCosmoDbCollection<T>(typeof(T));
var criteria = _client.CreateDocumentQuery<T>(
UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId), new FeedOptions { EnableCrossPartitionQuery = true })
.Where(predicate)
.OrderByDescending(orderByDesc)
.AsDocumentQuery();
IDocumentQuery<T> query = criteria;
List<T> results = new List<T>();
while (query.HasMoreResults)
{
if (takeCount > -1 && results.Count >= takeCount)
{
break;
}
results.AddRange(await query.ExecuteNextAsync<T>());
}
return results;
}
/// <summary>
///
/// </summary>
/// <param name="id"></param>
/// <param name="item"></param>
/// <returns></returns>
public async Task<Document> UpdateItemAsync<T>(string id, T item) where T : class
{
string CollectionId = GetAttributeCosmoDbCollection<T>(typeof(T));
return await _client.ReplaceDocumentAsync(UriFactory.CreateDocumentUri(DatabaseId, CollectionId, id), item);
}
#region private methods
private async Task CreateDatabaseIfNotExistsAsync()
{
try
{
await _client.ReadDatabaseAsync(UriFactory.CreateDatabaseUri(DatabaseId));
}
catch (DocumentClientException e)
{
if (e.StatusCode == System.Net.HttpStatusCode.NotFound)
{
await _client.CreateDatabaseAsync(new Database { Id = DatabaseId });
}
else
{
throw;
}
}
}
/// <summary>
///
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
private string GetPartitionKeyAttributeCosmoDbCollection(Type t)
{
// Get instance of the attribute.
CosmoDBCollection attribute =
(CosmoDBCollection)Attribute.GetCustomAttribute(t, typeof(CosmoDBCollection));
if (attribute == null)
{
throw new Exception("The attribute CosmoDbCollection was not found.");
}
return attribute.PartitionKey;
}
private string GetAttributeCosmoDbCollection<T>(Type t) where T : class
{
// Get instance of the attribute.
CosmoDBCollection attribute =
(CosmoDBCollection)Attribute.GetCustomAttribute(t, typeof(CosmoDBCollection));
if (attribute == null)
{
throw new Exception("The attribute CosmoDbCollection was not found.");
}
return attribute.Name;
}
#endregion
}
Here is CosmoDBCollection class:
public class CosmoDBCollection : Attribute
{
public string Name { get; set; }
public string PartitionKey { get; set; }
}
I am calling CreateCollectionIfNotExistsAsync().Wait(); in the constructor and this method required collectionId. How Can I pass CollectionId to this method? As this is the generic repository.
Do I need to create a Generic CreateCollectionIfNotExistsAsync() method?
If your collection name is based off <T>, why not simply have CosmosDBRepository<T> as the actual class. That way you can get the value also on the constructor.
Ideally it would also be a readonly private property that you only calculate once (on the constructor) and reuse on all operations to avoid paying the cost to construct it later on (since it doesn't change).
I have a OData service that returns a list of sharepoint lists.
I am unable to enumerate this list.
Is it possible to enumerate this to be able to loop through the lists in this Context in a foreach loop?
public class ODService
{
private DataContext _Context;
private NetworkCredential _nc;
public DataContext Context { get { return _Context; } }
/// <summary>
/// Constructor creates the context for access to sharepoint
/// </summary>
/// <param name="UserName">Service Account User Name</param>
/// <param name="Password">Service Account Password</param>
/// <param name="uri">Service uri</param>
public ODService(string UserName, string Password, string uri)
{
SetNetworkCredentials(UserName, Password);
SetContext(uri);
}
private void SetContext(string uri)
{
_Context = new DataContext(new Uri(uri));
_Context.Credentials = _nc;
_Context.MergeOption = MergeOption.NoTracking;
}
private void SetNetworkCredentials(string UserName, string Password)
{
_nc = new NetworkCredential(UserName, Password);
}
}
Got it:
public IList<string> EntityList()
{
IList<string> PropertyList = new List<string>();
var Properties = typeof(DataContext).GetProperties();
foreach (var property in Properties)
{
PropertyList.Add(property.Name);
}
return PropertyList;
}
I am not able to get advantage from the pub/sub StackExchange.Redis features.
This is my code.
Console application
using StackExchange.Redis;
using System;
using System.Data;
namespace RedisHashSets
{
class Program
{
static void Main(string[] args)
{
#region Prepare Data
var exampleData = new DataTable();
exampleData.Columns.Add("session_guid", typeof(String));
exampleData.Columns.Add("status_code", typeof(String));
exampleData.Columns.Add("date_open", typeof(DateTime));
exampleData.Columns.Add("date_expiry", typeof(DateTime));
exampleData.Columns.Add("extra_id", typeof(long));
exampleData.Columns.Add("current_real_balance", typeof(Decimal));
DataRow row = exampleData.NewRow();
row[0] = Guid.NewGuid();
row[1] = 1;
row[2] = DateTime.Now;
row[3] = DateTime.Now.AddMinutes(30);
row[4] = 44567;
row[5] = 10.34;
exampleData.Rows.Add(row);
#endregion
var redisClient = RedisProvider.Instance;
string guid = Guid.NewGuid().ToString();
// Add an Entry
redisClient.Set(guid, RedisDataMapper.GetHashSet(exampleData)[0]);
// Modify an Entry
HashEntry entry = new HashEntry("exrta_id", 338349);
redisClient.Set(guid, entry);
// Get an Entry
HashSet val = redisClient.Get(guid);
//Invalidate the key
redisClient.redisPubSub.Publish("InvalidateBalances", guid);
}
}
}
Redis Singletone Client
namespace RedisHashSets
{
/// <summary>
/// Provide access to the Redis capabilites used to store sesion. Used as a Singleton
/// </summary>
public class RedisProvider
{
#region Private Fields
private readonly static Lazy<RedisProvider> lazyObj = new Lazy<RedisProvider>(() => new RedisProvider());
private ConnectionMultiplexer redisClient;
private IDatabase redisDatabase;
private IServer currentServer;
private EndPoint[] endPoints;
#endregion Private Fields
#region Public Fields
public static RedisProvider Instance { get { return lazyObj.Value; } }
public ISubscriber redisPubSub;
public bool IsRedisEnableByConfig { get; set; }
#endregion Public Fields
#region Public Methods
private RedisProvider()
{
if (!lazyObj.IsValueCreated)
{
var conf = RedisConfig.GetConfiguration();
if (conf is null)
{
IsRedisEnableByConfig = false;
}
else
{
IsRedisEnableByConfig = true;
redisClient = ConnectionMultiplexer.Connect(conf);
redisDatabase = redisClient.GetDatabase(0);
endPoints = redisClient.GetEndPoints();
currentServer = redisClient.GetServer(endPoints.First());
ManageSubscriber();
}
}
}
private void ManageSubscriber()
{
redisPubSub = redisClient.GetSubscriber();
redisPubSub.Subscribe(new RedisChannel("InvalidateBalances", RedisChannel.PatternMode.Pattern), (channel, message) => MessageAction(message));
}
private void MessageAction(RedisValue message)
{
HashEntry updatedEntry = new HashEntry(HashSet.IsUpdatedFlag, false);
Set(message, updatedEntry);
}
public void Set(string key, HashSet value)
{
redisDatabase.HashSet(key, value.Entries);
Set(key, value.IsUpdated);
}
public void Set(string key, HashEntry value)
{
redisDatabase.HashSet(key, value.Name, value.Value);
}
/// <summary>
/// Get a value from Redis.
/// </summary>
/// <param name="key">The key of the vaule to retrive</param>
/// <returns>Cast the value and retrurn a strongly typed object</returns>
public HashSet Get(string key)
{
HashEntry[] value = redisDatabase.HashGetAll(key);
return new HashSet(value.Length) { Entries = value };
}
/// <summary>
/// Check if a value is in stored or not expired. Time consuming. Use onky if necessary.
/// </summary>
/// <param name="key">The key of the value</param>
public bool IsInCache(string key)
{
return redisDatabase.KeyExists(key);
}
/// <summary>
/// Remove a value from the cache.
/// </summary>
/// <param name="key">The key to remove</param>
public bool Remove(string key)
{
return redisDatabase.KeyDelete(key);
}
/// <summary>
/// Return the number of active keys stored inside the redis databaase.
/// </summary>
public int GetKeysNumber()
{
var retVal = 0;
retVal = currentServer.Keys().Count();
return retVal;
}
/// <summary>
/// Return an enumerable of all the Keys.
/// </summary>
public IEnumerable<string> GetKeys()
{
return currentServer.Keys().Select(k => k.ToString());
}
#endregion
}
}
When I publish a message, it is not catched by the subscriber.
Can you help me?
Try to check you configuration.
Your code is working for me with the "localhost" as the connection string i.e
redisClient = ConnectionMultiplexer.Connect("localhost");
This is the minimal version of your code which is working for me in a console app.
using StackExchange.Redis;
using System;
using System.Linq;
using System.Net;
namespace RedisHashSets
{
class Program
{
static void Main(string[] args)
{
var redisClient = RedisProvider.Instance;
for (int i = 0; i < 10; i++)
{
//Thread.Sleep(100);
redisClient.redisPubSub.Publish("InvalidateBalances", Guid.NewGuid().ToString());
}
Console.ReadLine();
}
}
public class RedisProvider
{
#region Private Fields
private static readonly Lazy<RedisProvider> lazyObj = new Lazy<RedisProvider>(() => new RedisProvider());
private ConnectionMultiplexer redisClient;
private IDatabase redisDatabase;
private IServer currentServer;
private EndPoint[] endPoints;
public static RedisProvider Instance => lazyObj.Value;
public ISubscriber redisPubSub;
public bool IsRedisEnableByConfig { get; set; }
private RedisProvider()
{
if (!lazyObj.IsValueCreated)
{
IsRedisEnableByConfig = true;
redisClient = ConnectionMultiplexer.Connect("localhost");
endPoints = redisClient.GetEndPoints();
currentServer = redisClient.GetServer(endPoints.First());
ManageSubscriber();
}
}
private void ManageSubscriber()
{
redisPubSub = redisClient.GetSubscriber();
redisPubSub.Subscribe(new RedisChannel("InvalidateBalances", RedisChannel.PatternMode.Pattern), (channel, message) => MessageAction(message));
}
private void MessageAction(RedisValue message)
{
Console.WriteLine("msg arrived: " + message);
}
#endregion
}
}
Also please keep your code examples minimal complete and verifiable.
I am working on a project where I plan on using Redis as persistent data storage, however the task at hand, I am working on a generic Object cache. and as a huge fan of LINQ I have started designing a cache which does support this.
public ConcurrentBag<Object> Cache = new ConcurrentBag<object>();
public List<T> FindBy<T>(Func<T, bool> predicate) where T : class
{
var tmp = new List<T>();
foreach (var i in Cache)
{
try
{
T obj = i as T;
if (obj != null)
tmp.Add(obj);
}
catch { }
}
return tmp.Where(predicate).ToList();
}
I am afraid that when the object cache grows large it will become inefficient. (I estimate 500k-1m objects)
I was hoping that it would be possible to use something like this
public ConcurrentBag<Object> Cache = new ConcurrentBag<object>();
public List<T> FindBy<T>(Func<T, bool> predicate) where T : class
{
return Cache.Where<T>(predicate).ToList();
}
Hopefully I am not all off-track here? Any suggestions are welcome :)
Hash your genric type and save list of specific type..
Something like:
Dictionary<Type,List<T>>
Then get value by type key and query as you wanted
Since you estimate a lot of items in the cache and the operations on the cache will be type specific, you could use multiple bags wrapped into a dictionary. That would speed up finding the subset of the cache of type of interest and would be ideal if the cache contained many minimal subsets of different types.
readonly IDictionary<Type, ConcurrentBag<object>> _cache = new ConcurrentDictionary<Type, ConcurrentBag<object>>();
public List<T> FindBy<T>(Func<T, bool> predicate) where T : class
{
// Check if items of type {T} exist in the cache.
ConcurrentBag<object> bag;
if (_cache.TryGetValue(typeof (T), out bag))
{
// Cast, apply predicate and return.
return bag.Cast<T>().Where(predicate).ToList();
}
// Return an empty list.
return new List<T>();
}
Of course now you also need to handle adding items properly to the cache to ensure that different types will be put into their corresponding bags.
Big thanks to both Discosultan and user1190916 Whom both pointed me in the right direction in what I needed to get a CRUD cached-object repository with full LINQ support using Redis for persistent storage (Client ServiceStack.Redis), this is what I have managed to conjure up thus far.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Collections.Concurrent;
using ServiceStack.Redis;
namespace RedisTestRepo
{
class Program
{
//public static DataRepository Db;
static void Main(string[] args)
{
Repo r = new Repo();
// We do not touch sequence, by running example we can see that sequence will give Users new unique Id.
// Empty data store.
Console.WriteLine("Our User Data store should be empty.");
Console.WriteLine("Users In \"Database\" : {0}\n", r.All<User>().Count);
// Add imaginary users.
Console.WriteLine("Adding 100 imaginairy users.");
for (int i = 0; i < 99; i++)
r.Create<User>(new User { Id = r.Next<User>(), Name = "Joachim Nordvik" });
// We should have 100 users in data store.
Console.WriteLine("Users In \"Database\" : {0}\n", r.All<User>().Count);
// Lets print 10 users from data store.
Console.WriteLine("Order by Id, Take (10) and print users.");
foreach (var u in r.All<User>().OrderBy(z => z.Id).Take(10))
{
Console.WriteLine("ID:{0}, Name: {1}", u.Id, u.Name);
// Lets update an entity.
u.Name = "My new Name";
r.Update<User>(x=>x.Id == u.Id, u);
}
// Lets print 20 users from data store, we already edited 10 users.
Console.WriteLine("\nOrder by Id, Take (20) and print users, we previously edited the users that we printed lets see if it worked.");
foreach (var u in r.All<User>().OrderBy(z => z.Id).Take(20))
{
Console.WriteLine("ID:{0}, Name: {1}", u.Id, u.Name);
}
// Clean up data store.
Console.WriteLine("\nCleaning up Data Store.\n");
foreach (var u in r.All<User>())
r.Delete<User>(u);
// Confirm that we no longer have any users.
Console.WriteLine("Confirm that we no longer have User entities in Data Store.");
Console.WriteLine("Users In \"Database\" : {0}\n\n", r.All<User>().Count);
Console.WriteLine("Hit return to exit!");
Console.Read();
}
}
public class Repo
{
private static readonly PooledRedisClientManager m = new PooledRedisClientManager();
public Repo()
{
// Spool Redis Database into our object cache.
LoadIntoCache<User>();
}
readonly IDictionary<Type, List<object>> _cache = new ConcurrentDictionary<Type, List<object>>();
/// <summary>
/// Load {T} into object cache from Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
private void LoadIntoCache<T>() where T : class
{
_cache[typeof(T)] = GetAll<T>().Cast<object>().ToList();
}
/// <summary>
/// Add single {T} into cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="entity">class object</param>
public void Create<T>(T entity) where T : class
{
List<object> list;
if (!_cache.TryGetValue(typeof(T), out list))
{
list = new List<object>();
}
list.Add(entity);
_cache[typeof(T)] = list;
Store<T>(entity);
}
/// <summary>
/// Delete single {T} from cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="entity">class object</param>
public void Delete<T>(T entity) where T : class
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
list.Remove(entity);
_cache[typeof(T)] = list;
RedisDelete<T>(entity);
}
}
/// <summary>
/// Tries to update or Add entity to object cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq expression</param>
/// <param name="entity">entity</param>
public void Update<T>(Func<T, bool> predicate, T entity) where T : class
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
// Look for old entity.
var e = list.Cast<T>().Where(predicate).FirstOrDefault();
if(e != null)
{
list.Remove(e);
}
// Regardless if object existed or not we add it to our Cache / Data Store.
list.Add(entity);
_cache[typeof(T)] = list;
Store<T>(entity);
}
}
/// <summary>
/// Find List<T>(predicate) in cache.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq statement</param>
/// <returns></returns>
public List<T> FindBy<T>(Func<T, bool> predicate) where T : class
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
return list.Cast<T>().Where(predicate).ToList();
}
return new List<T>();
}
/// <summary>
/// Find All {T}
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns>List<T></returns>
public List<T> All<T>() where T : class
{
return GetAll<T>().ToList();
}
/// <summary>
/// Find Single {T} in object cache.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq statement</param>
/// <returns></returns>
public T Read<T>(Func<T, bool> predicate) where T : class
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
return list.Cast<T>().Where(predicate).FirstOrDefault();
}
return null;
}
public long Next<T>() where T : class
{
long id = 1;
using (var ctx = m.GetClient())
{
try
{
id = ctx.As<T>().GetNextSequence();
}
catch(Exception ex)
{
// Add exception handler.
}
}
return id;
}
private void RedisDelete<T>(T entity) where T : class
{
using (var ctx = m.GetClient())
ctx.As<T>().Delete(entity);
}
private T Find<T>(long id) where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetById(id);
}
private IList<T> GetAll<T>() where T : class
{
using(var ctx = m.GetClient())
{
try
{
return ctx.As<T>().GetAll();
}
catch
{
return new List<T>();
}
}
}
private void Store<T>(T entity) where T : class
{
using (var ctx = m.GetClient())
ctx.Store<T>(entity);
}
}
public class User
{
public long Id { get; set; }
public string Name { get; set; }
}
}
I tried searching for this but I'm not even sure how to phrase it for the search.
What I'm attempting to do is have a class that everytime I access it to change it, I'm really getting and setting the value from session.
Here's what I'm trying to do (what I have so far.):
public class example
{
public int prop1 {get;set;}
public static example Instance
{
return (example)(HttpContext.Current.Session["exampleClass"] ?? new example());
}
}
public class main
{
protected void Page_Load(object sender, EventArgs e)
{
example.Instance.prop1 = "aaa"; //stores value into session
txtInput.Text = example.Instance.prop1; //retrieves value from session
}
}
I hope that makes sense on what I am trying to do.
Any help would be appreciated, thank you.
This would be easy to do with generics.
Give this a try.
public class Session
{
public User User
{
get { return Get<User>("User"); }
set {Set<User>("User", value);}
}
/// <summary> Gets. </summary>
/// <typeparam name="T"> Generic type parameter. </typeparam>
/// <param name="key"> The key. </param>
/// <returns> . </returns>
private T Get<T>(string key)
{
object o = HttpContext.Current.Session[key];
if(o is T)
{
return (T) o;
}
return default(T);
}
/// <summary> Sets. </summary>
/// <typeparam name="T"> Generic type parameter. </typeparam>
/// <param name="key"> The key. </param>
/// <param name="item"> The item. </param>
private void Set<T>(string key, T item)
{
HttpContext.Current.Session[key] = item;
}
}
It looks like you're pretty close, but you don't have anything to actually store the object in session. Try something like this:
public static Example Instance
{
get
{
//store the object in session if not already stored
if (Session["example"] == null)
Session["example"] = new Example();
//return the object from session
return (Example)Session["example"];
}
}
This is basically just a web-friendly implementation of the Singleton Pattern.
using System.Web;
using System.Web.SessionState;
using System.Collections.Generic;
public static class ExampleSession
{
private static HttpSessionState session { get { return HttpContext.Current.Session; } }
public static string UserName
{
get { return session["username"] as string; }
set { session["username"] = value; }
}
public static List<string> ProductsSelected
{
get
{
if (session["products_selected"] == null)
session["products_selected"] = new List<string>();
return (List<string>)session["products_selected"];
}
}
}
and you can use it like so:
public class main
{
protected void Page_Load(object sender, EventArgs e)
{
//stores value into session
ExampleSession.UserName = "foo";
ExampleSession.ProductsSelected.Add("bar");
txtInput.Text = ExampleSession.UserName; //retrieves value from session
}
}
public class example {
public int prop1 { get; set; }
public static example Instance {
var exampleObject = (example)(HttpContext.Current.Session["exampleClass"]
?? new example());
HttpContext.Current.Session["exampleClass"] = exampleObject;
return exampleObject;
}
}
you can optimize it further if needed
If you're looking for a more object oriented way of doing session here is a good way of doing it below.
UserSession Class
[Serializable()]
public class UserSession
{
private CurrentRecord _CurrentRecord;
public CurrentRecord CurrentRecord
{
get
{
if ((_CurrentRecord == null))
{
_CurrentRecord = new CurrentRecord();
}
return _CurrentRecord;
}
set
{
if ((_CurrentRecord == null))
{
_CurrentRecord = new CurrentRecord();
}
_CurrentRecord = value;
}
}
}
Globals Class
public static class Globals
{
public static UserSession TheUserSession
{
get
{
if ((HttpContext.Current.Session["UserSession"] == null))
{
HttpContext.Current.Session.Add("UserSession", new CurrentUserSession());
return (CurrentUserSession)HttpContext.Current.Session["UserSession"];
}
else
{
return (CurrentUserSession)HttpContext.Current.Session["UserSession"];
}
}
set { HttpContext.Current.Session["UserSession"] = value; }
}
}
CurrentRecord class
[Serializable()]
public class CurrentRecord
{
public int id { get; set; }
public string name { get; set; }
}
Usage in code behind
public void SetRecordId(int newId)
{
Globals.TheUserSession.CurrentRecord.id = newId;
}