I have a View which is using
Session["Something"] = 1;
And I have a class inside a class library project that tries to get this value from the session using
HttpContext.Current.Session["Something"]
But it retuns null.
public ActionResult Index()
{
Session["Something"] = 1;
var fromLib = (new MyLibClass()).GetSession("Something"); // null
var fromHere = Session["Something"]; // 1
}
// Class library project
public object GetSession(string key)
{
return HttpContext.Current.Session[key];
}
How can I get the value from the session? Or is there a way to save a value and retrieve in another place (without database or system files)
You don't need Session object.
Although Session is good for holding variables inside an asp.net application you can implement your own session object for using inside your class libraries which is light and fast and internal to your code:
Dictionary<string, object> MySession = new Dictionary<string, object>();
MySession.Add("VariableName", myObject);
MyLib.Pass(MySession);
Try to keep it more specific if possible i.e. if you just pass MyClass to your library then:
Dictionary<string, MyClass> MySession = new Dictionary<string, MyClass>();
There are two sessions
Session (refers to the view session)
HttpContext.Current.Session (refers to context session)
Using HttpContext.Current.Session everywhere works as they are the same. I made a class to help me access the session values the way I want, so I can just call it without worrying about the correct session.
Related
I will use many times a collection that I have in my database, I want to store it in a Session variable so I will not need to read the database every time that I want to have access to that collection(I accept suggestions if you have a better idea to do this instead of using a session variable). In Asp.Net MVC it was pretty easy, just assign the collection to the variable, but in ASP.net Core MVC even if I'm working with the .net Framework is different, I made the configurations that I needed to do in Startup.cs already, the problem is that Session in ASP.net Core only have implemented these methods(this is an example taken from here):
public IActionResult Index()
{
HttpContext.Session.SetString("Name", "Mike");
HttpContext.Session.SetInt32("Age", 21);
return View();
}
They show you an example of how to implement an extension method to store boolean types in a Session variable. But what if I want to store a collection? How could I do that? Let's say that I have a table called Person with fields like name, age, etc. and I want to store a collection of Person objects in a Session variable, how could I do that?
If you want to store complex object in Session then you can do like this-
public static class SessionExtensions
{
public static void SetObjectAsJson(this ISession session, string key, object value)
{
session.SetString(key, JsonConvert.SerializeObject(value));
}
public static T GetObjectFromJson<T>(this ISession session, string key)
{
var value = session.GetString(key);
return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
}
}
To store complex object, you can do like this-
var obj= new ComplexClass();
HttpContext.Session.SetObjectAsJson("SessionVariable1", obj);
And read back like this-
var obj= HttpContext.Session.GetObjectFromJson<ComplexClass>("SessionVariable1");
See if this helps.
For application-wide caching (same values for all users) use Caching, for example MemoryCaching
I have face a requirement,
I want client access a data center but without use database , so I want my web app can retain a global or Application session variable, that contains the data, every client can access the same data... I am try to declare in golabl, but seem it only can store String but others ...
how to solve this problem ?
thanks.
Another option of defining a global variable is by creating a static class with a static property:
public static class GlobalVariables
{
public static string MyGlobalVariable { get; set; }
}
You can make this more complex if you are going to use this as a data store, but the same idea goes. Say, you have a dictionary to store your global data, you could do something like this:
public static class GlobalData
{
private static readonly object _syncRoot = new object();
private static Dictionary<string, int> _data;
public static int GetItemsByTag(string tag)
{
lock (_syncRoot)
{
if (_data == null)
_data = LoadItemsByTag();
return _data[tag];
}
}
private static Dictionary<string, int> LoadItemsByTag()
{
var result = new Dictionary<string, int>();
// Load the data from e.g. an XML file into the result object.
return result;
}
}
To Share the data with all application users, you can use ASP.NET Application object. Given is the sample code to access Application object in ASP.NET:
Hashtable htblGlobalValues = null;
if (Application["GlobalValueKey"] != null)
{
htblGlobalValues = Application["GlobalValueKey"] as Hashtable;
}
else
{
htblGlobalValues = new Hashtable();
}
htblGlobalValues.Add("Key1", "Value1");
htblGlobalValues.Add("Key2", "Value2");
this.Application["GlobalValueKey"] = htblGlobalValues;
Application["GlobalValueKey"] can be used anywhere in the whole application by any user. It will be common to all application users.
You can stuff data into the Application object if you want. It isn't persistent across application instances, but that may sufficient.
(I'm not for a minute going to suggest this is a best practice, but without a clearer picture of the requirements, that's all I can suggest.)
http://msdn.microsoft.com/en-us/library/system.web.ui.page.application.aspx
http://msdn.microsoft.com/en-us/library/system.web.httpapplication.aspx
If you are using WebApplication or MVC just go to Global.asax (in WebSite project you need to add Global.asax from the add new item menu).
I will explain to deploy two global variables for your web application:
Open the Global.asax file, then define your variable in Application_Start function as following:
void Application_Start(object sender, EventArgs e)
{
Application.Lock();
Application["variable1"] = "Some Value for variable1";
Application["variable2"] = "Some Value for variable2";
Application.UnLock();
}
If you want to use that those global variables in aspx pages just need to call them like this:
<p>I want to call variable1 <%=Application["variable1"].ToString() %></p>
<p>I want to call variable1 <%=Application["variable2"].ToString() %></p>
But if you want to use that those global variables in server-side call'em like this:
protected void Page_Load(object sender, EventArgs e)
{
string str1 = Application["variable1"].ToString();
string str2 = Application["variable2"].ToString();
}
Note: You must be aware that these global variables are public to all users and aren't suitable for authentication jobs.
You can also use Cache, which has advantages like ability to set expire time/date.
Given that I have the following WCF service:
class LookUpService
{
public List<County> GetCounties(string state)
{
var db = new LookUpRepository();
return db.GetCounties(state);
}
}
class County
{
public string StateCode{get;set;}
public string CountyName{get;set;}
public int CountyCode{get;set;}
}
What will be the most efficient (or best) way to cache a state's counties using weak references (or any other approach) so that we don't hit the database every time we need to look up data.
Note that we will not have access to the HttpRuntime (and HttpContext).
For this scenario you're going to want to use a WeakReference style hash table of sorts. None is available in the BCL (until 4.0) but there are several available online. I will be using the following for this sample
http://blogs.msdn.com/jaredpar/archive/2009/03/03/building-a-weakreference-hashtable.aspx
Try the following cdoe
class LookupService {
private WeakHashtable<string,List<Count>> _map = new WeakHashtable<string,List<County>>();
public List<County> GetCounties(string state) {
List<Count> found;
if ( !_map.TryGetValue(state, out found)) {
var db = new LookUpRepository();
found = db.GetCounties(state);
_map.Add(state,found);
}
return found;
}
}
As you can see, it's not much different than using a normal Dictionary<TKey,TValue>
Why do you not have acccess to HttpRuntime? You don't need the context. You only need the class.
You can use System.Web.Caching in a non-ASP.NET app, without using the HttpContext.
see also Caching in WCF?
I've created a custom resource provider which returns strings from our database to use for whatever.
The issue is I haven't found a way to "bust" the cache on these items and reload them from the database. Ideally I'd do this every x minutes or manually when we update the cache and want to reload it.
Technically, that's easy. I'm storing everything in a hashtable so just nuke that and reload when needed. However since the ResourceProviderFactory handles the loading of each resource class and I'm not sure how to enumerate the classes it has created.
An overview of the code:
public class ResourceProvider : IResourceProvider
{
private Dictionary<string, Dictionary<string, object>> _resourceCache
= new Dictionary<string, Dictionary<string, object>>();
private string _virtualPath;
private string _className;
public ResourceProvider(string virtualPath, string className)
{
_virtualPath = virtualPath;
_className = className;
}
public object GetObject(string resourceKey, CultureInfo culture)
{
...
}
}
public class ResourceProviderFactory :System.Web.Compilation.ResourceProviderFactory
{
public override IResourceProvider CreateGlobalResourceProvider(string classKey)
{
return new Cannla.Business.Resource.ResourceProvider(string.Empty, classKey);
}
...
...
}
What I was planning to do was add a reference every time CreateGlobalResourceProvider is called (e.g. add the new object to a collection and then enumerate that and nuke everything inside that object when I need to) but I'm unsure if this is going to do something weird to the ResourceProviderFactory.
Is there any ResourceProviderFactory IEnumerable method or something that will give me all those objects in a easy way before I go building all this code?
If you can use ASP.Net cache system
Just use it. You can access it using HttpRuntime.Cache and add timed invalidation check the example below:
var Key = "Resources:" + ResourceType + ResourceKey + Cutlure.Name;
HttpRuntime.Cache.Insert(Key, ValueToCache,
null, DateTime.Now.AddMinutes(1d),
System.Web.Caching.Cache.NoSlidingExpiration);
If you can't use ASP.Net cache system
You can put the logic that triggers cache invalidation inside of IResourceProvider.
ie. just check in GetObject if the cache expired.
I have created a class file in the App_Code folder in my application. I have a session variable
Session["loginId"]
I want to access this session variables in my class, but when I am writing the following line then it gives error
Session["loginId"]
Can anyone tell me how to access session variables within a class which is created in app_code folder in ASP.NET 2.0 (C#)
(Updated for completeness)
You can access session variables from any page or control using Session["loginId"] and from any class (e.g. from inside a class library), using System.Web.HttpContext.Current.Session["loginId"].
But please read on for my original answer...
I always use a wrapper class around the ASP.NET session to simplify access to session variables:
public class MySession
{
// private constructor
private MySession()
{
Property1 = "default value";
}
// Gets the current session.
public static MySession Current
{
get
{
MySession session =
(MySession)HttpContext.Current.Session["__MySession__"];
if (session == null)
{
session = new MySession();
HttpContext.Current.Session["__MySession__"] = session;
}
return session;
}
}
// **** add your session properties here, e.g like this:
public string Property1 { get; set; }
public DateTime MyDate { get; set; }
public int LoginId { get; set; }
}
This class stores one instance of itself in the ASP.NET session and allows you to access your session properties in a type-safe way from any class, e.g like this:
int loginId = MySession.Current.LoginId;
string property1 = MySession.Current.Property1;
MySession.Current.Property1 = newValue;
DateTime myDate = MySession.Current.MyDate;
MySession.Current.MyDate = DateTime.Now;
This approach has several advantages:
it saves you from a lot of type-casting
you don't have to use hard-coded session keys throughout your application (e.g. Session["loginId"]
you can document your session items by adding XML doc comments on the properties of MySession
you can initialize your session variables with default values (e.g. assuring they are not null)
Access the Session via the thread's HttpContext:-
HttpContext.Current.Session["loginId"]
The problem with the solution suggested is that it can break some performance features built into the SessionState if you are using an out-of-process session storage. (either "State Server Mode" or "SQL Server Mode"). In oop modes the session data needs to be serialized at the end of the page request and deserialized at the beginning of the page request, which can be costly. To improve the performance the SessionState attempts to only deserialize what is needed by only deserialize variable when it is accessed the first time, and it only re-serializes and replaces variable which were changed. If you have alot of session variable and shove them all into one class essentially everything in your session will be deserialized on every page request that uses session and everything will need to be serialized again even if only 1 property changed becuase the class changed. Just something to consider if your using alot of session and an oop mode.
The answers presented before mine provide apt solutions to the problem, however, I feel that it is important to understand why this error results:
The Session property of the Page returns an instance of type HttpSessionState relative to that particular request. Page.Session is actually equivalent to calling Page.Context.Session.
MSDN explains how this is possible:
Because ASP.NET pages contain a default reference to the System.Web namespace (which contains the HttpContext class), you can reference the members of HttpContext on an .aspx page without the fully qualified class reference to HttpContext.
However, When you try to access this property within a class in App_Code, the property will not be available to you unless your class derives from the Page Class.
My solution to this oft-encountered scenario is that I never pass page objects to classes. I would rather extract the required objects from the page Session and pass them to the Class in the form of a name-value collection / Array / List, depending on the case.
In asp.net core this works differerently:
public class SomeOtherClass
{
private readonly IHttpContextAccessor _httpContextAccessor;
private ISession _session => _httpContextAccessor.HttpContext.Session;
public SomeOtherClass(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public void TestSet()
{
_session.SetString("Test", "Ben Rules!");
}
public void TestGet()
{
var message = _session.GetString("Test");
}
}
Source: https://benjii.me/2016/07/using-sessions-and-httpcontext-in-aspnetcore-and-mvc-core/
I had the same error, because I was trying to manipulate session variables inside a custom Session class.
I had to pass the current context (system.web.httpcontext.current) into the class, and then everything worked out fine.
MA
This should be more efficient both for the application and also for the developer.
Add the following class to your web project:
/// <summary>
/// This holds all of the session variables for the site.
/// </summary>
public class SessionCentralized
{
protected internal static void Save<T>(string sessionName, T value)
{
HttpContext.Current.Session[sessionName] = value;
}
protected internal static T Get<T>(string sessionName)
{
return (T)HttpContext.Current.Session[sessionName];
}
public static int? WhatEverSessionVariableYouWantToHold
{
get
{
return Get<int?>(nameof(WhatEverSessionVariableYouWantToHold));
}
set
{
Save(nameof(WhatEverSessionVariableYouWantToHold), value);
}
}
}
Here is the implementation:
SessionCentralized.WhatEverSessionVariableYouWantToHold = id;