I'm working on creating a session for a user login on my website. I can initialize the session and use its members just fine, but I also need a method within my session class that will store itself. I need to provide HttpSessionState as an input parameter, and then store it into an object like: Session["sessionName"]=this;.
Furthermore, when I want to retrieve the session, it won't yet be created, so it must be static. Then I need to return a new instance of my session class with the properties filled (username and companyID) out of the HttpSessionState.
How can this be done in my session class? What I've described above is from the research I've done that provides a particular solution to my problem, but since I'm new to using session, I don't quite understand it.
Thanks.
Snippet of my session class:
public class MySession : System.Web.UI.Page
{
private MySession()
{
Username = Business.User.labelUsername;
CompanyId = Business.User.labelCompanyId;
}
public static MySession Current
{
get
{
try
{
MySession session = (MySession)HttpContext.Current.Session["sessionName"];
if (session == null)
{
session = new MySession();
HttpContext.Current.Session["sessionName"]=session;
}
return session;
}
catch (NullReferenceException e)
{
Debug.WriteLine("NullReferenceException:");
Debug.WriteLine(e);
}
return null;
}
}
public string Username
{
get; set;
}
public string CompanyId
{
get; set;
}
}
You could try using a serialized "session info" object:
[Serializable]
public class SessionInfo
{
// Stuff to store in session
public string Name { get; set; }
public int Foo { get; set; }
private SessionInfo()
{
// Constructor, set any defaults here
Name = ""
Foo = 10;
}
public static SessionInfo Current
{
get
{
// Try get session info from session
var info = HttpContext.Current.Session["SessionInfo"] as SessionInfo;
// Not found in session, so create and store new session info
if (info == null)
{
info = new SessionInfo();
HttpContext.Current.Session["SessionInfo"] = info;
}
return info;
}
}
}
You can then use this from within your application like this:
SessionInfo.Current.Name = "Something Here";
SessionInfo.Current.Foo = 100;
The serialization/deserialization is all done within the SessionInfo object, and you get the benefit of type safe data.
What you are asking about is called serialization and deserialization.
Serialization is taking an object and converting it to a format, such as a string, that can be stored. Deserialization is the reverse of that action.
The "quick" way is to add the [Serializable] attribute to your class. However, without knowing the details of that class it's hard to say whether it is in fact easily serializable without a bit of work.
Here's a walkthrough: http://msdn.microsoft.com/en-us/library/vstudio/et91as27.aspx
Related
I'm developing 3rd party API connector bridge in class library NOT in ASP.NET.
User Levels
API has 3 user levels, lets say:
UserGoer
UserDoer
UserMaker
Service Restriction
Each API operation can work with one or multiple user level roles. For example, lets assume operations and reachable user levels as follows;
JokerService (reachable by UserGoer, UserMaker)
PokerService (reachable by UserGoer, UserDoer)
MokerService (reachable by UserGoer, UserDoer, UserMaker)
If UserDoer requests for JokerService, API returns bad request. JokerService is only reachable for UserGoer and UserMaker. So, I want to restrict and throw an exception.
User Token Structure
public interface IToken
{
string AccessToken { get; set; }
string RefreshToken { get; set; }
}
public class AuthenticationToken : IToken
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
[JsonProperty("refresh_token")]
public string RefreshToken { get; set; }
}
public class UserGoerAuthenticationToken : AuthenticationToken
{
}
public class UserDoerAuthenticationToken : AuthenticationToken
{
}
public class UserMakerAuthenticationToken : AuthenticationToken
{
}
Enum
public enum TokenType
{
Undefined = 0,
UserGoer = 1,
UserDoer = 2,
UserMaker = 3
}
Customized Authentication Attribute
public class AuthenticationFilter : Attribute
{
public TokenType[] TokenTypes { get; private set; }
public AuthenticationFilter(params TokenType[] TokenTypes)
{
this.TokenTypes = TokenTypes;
}
}
Example Service
[AuthenticationFilter(TokenType.UserGoer, TokenType.UserMaker)]
internal class JokerService : BaseService<JokerEntity>
{
public JokerService(IToken AuthenticationToken) : base(AuthenticationToken)
{
var tokenTypes =
(typeof(JokerService).GetCustomAttributes(true)[0] as AuthenticationFilter)
.TokenTypes;
bool throwExceptionFlag = true;
foreach (var item in tokenTypes)
{
// Check AuthenticationToken is UserGoer or UserMaker by StartsWith function
if (AuthenticationToken.GetType().Name.StartsWith(item.ToString()))
{
throwExceptionFlag = false;
break;
}
}
if (throwExceptionFlag)
throw new Exception("Invalid Authentication Token");
}
public JokerEntity Create(RequestModel<JokerEntity> model) => base.Create(model);
public JokerEntity Update(RequestModel<JokerEntity> model) => base.Update(model);
public JokerEntity Get(RequestModel<JokerEntity> model) => base.Get(model);
public List<JokerEntity> List(RequestModel<JokerEntity> model) => base.List(model);
}
In summary, JokerService can be executable by UserGoer and UserMaker. UserDoer has no permission for this service.
As you see the the usage of AuthenticationFilter attribute, I'm getting custom attributes in the constructor, because i want to know what IToken is. If there is an irrelevant "User Authentication Token" type that is passed as parameter (IToken), program should be throw an exception.
This is my solution, do you think is there any best practice for my problem?
Thank you for your help.
Interesting question. My initial thought at constructive critique would be that the tokens accepted by a particular class via the attribute is something decided at compile time and is unable to change. But, the checking for permissions is happening on the construction of each object.
You can prevent this with a static constructor that sets the tokenTypes variable. Static constructors always run before instance constructors. This is also a good place to ensure that tokenTypes is never null (in the absence of your custom attribute).
Likewise, the looping through tokenTypes can probably be a function that takes in an IToken and the tokenTypes, and more importantly, could probably live in the BaseService.cs. Writing that logic once will make it easier to maintain when some future requirement necessitates its change. :)
See also: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-constructors
Hope this helps.
I have online exam system I want to save username in global variable or any other thing that just can save it.
I want this username for get and set data on SQL database.
I'm using a global variable in class but it replace in every login.
any way to save username foreach user?
public class GVar
{
public static string user
{
get; set;
}
public static string mail
{
get;
set;
}
public static string melli
{
get;
set;
}
public static bool go
{
get;
set;
}
public static System.Threading.Thread thread { get; set; }
}
Use Application or Session as the case may be.
Session variables are global but limited to current session (call it user for understanding).
Application variables are globally shared across all sessions.
So, following statements may be used to get/set variables at application level
Application["user"] = "abc"; //sets the value at application level
var user = Application["user"]; //gets the value stored at application level
Similarly, to make it global, but isolate at session level,
Session["user"] = "abc"; //sets the value at session level
var user = Session["user"]; //gets the value stored at session level
EDIT
For ease of use, I prefer implementing them as properties, somewhat like this:
Define the class with custom getter/setter properties, and add it to App_Code folder
public static class GVar
{
public static string user
{
get { return Session["GVar_User"]; }
set { Session["GVar_User"] = value; }
}
//...
}
Use it in your application, as you would normally do with any other property.
GVar.user = "abc"; //set value
var usr = GVar.user; //get value
You can save it on login like this:
Session["user"] = "gamesdl";
And then you can get the value during executing like this:
String username = (string)(Session["user"]);
You can use claims.
The claims are in identity. And you can config then in login action.
I don't know why i can't find an easy quick lookup for this on the web but i was wondering what the relationship is between Deserializing an XML representation of an object and the constructor for that object?
I am assuming it uses the Default Constructor. And if that's the case, it will run the code in the constructor, but not update the object itself after that to reflect the XML?
Here's a bit more context on what i mean...
I have an object with two properties that are actually objects as well:
public class Deployment
{
public AppPoolSettings AppPool { get; set; }
public WebSiteSettings Site { get; set; }
public Deployment()
{
//the object constructors below init their internal properties as well...
this.AppPool = new AppPoolSettings();
this.Site = new WebSiteSettings();
}
}
The problem I am currently having is that in the XML, the AppPool property can be null (say, if you're deploying an HTML only package). The serialization procedure works properly, that is to say, the resulting XML only contains an entry for Site, and no entry for AppPool.
However, when I deserialize that XML, the AppPool property of my Deployment object is always instantiated and initialized... which is not what the XML is saying.
Am I doing something wrong or is it really just because of the default constructor?
See I would've expected the deserializer to perform the tasks in this order:
1- Call default constructor
2- Does AppPool property exist in XML?
Yes --> Fill,
No --> Set to NULL
3- Does the Site property exist in XML?
Yes --> Fill,
No --> Set to NULL
Why is it not doing that?
I believe the correct answer is: yes, counterintuitive handling of null properties (omitting them in serialized data and doing nothing with them on deserialization) is a feature of XmlSerializer. But you can override that behavior and force XmlSerializer to write nulls to XML with attributes like that:
public class Deployment
{
[XmlElement(IsNullable = true)]
public AppPoolSettings AppPool { get; set; }
[XmlElement(IsNullable = true)]
public WebSiteSettings Site { get; set; }
public Deployment()
{
//the object constructors below init their internal properties as well...
this.AppPool = new AppPoolSettings();
this.Site = new WebSiteSettings();
}
}
then you'll get <AppPool xsi:nil="true" /> in XML and expected deserialization.
The default constructor is called, and therefore, Site and AppPool are assigned. If you want them be null maybe you could try this code:
public class Deployment
{
private AppPoolSettings appPool;
public AppPoolSettings AppPool
{
get { return appPool; }
set
{
// if (appPool == null)
// appPool = new AppPoolSettings();
appPool = value;
}
}
private WebSiteSettings site;
public WebSiteSettings Site
{
get { return site; }
set
{
// if (site == null)
// site = new WebSiteSettings();
site = value;
}
}
public Deployment()
{
// No instatiation anymore...
}
}
You expectations are wrong. XmlSerializer will construct object (by calling parameterless constructor, if there is none - exception is thrown). Then properties will be populated one by one using some reflection magic.
So what happens:
Constructor is called, in which you set values of AppPool and Site.
There is Site property in xml, it's deserialized and assigned.
But there is no AppPool in xml, so nothing changes and its value stay (not null).
To have null for AppPool you should not set its value in constructor. Then it will stay such if missing in xml.
Here is one possible solution:
public class Deployment
{
public AppPoolSettings AppPool { get; set; }
public WebSiteSettings Site { get; set; }
// used by deserializer
public Deployment() { }
// use this to construct object
public static Deployment Create()
{
return new Deployment()
{
AppPool = new AppPoolSettings(),
Site = new WebSiteSettings()
};
}
}
I have a class called "Account".
Here are my codes:
// Account.cs
public partial class Account
{
private Account.Credential _credential = new Account.Credential();
public void Login(string UserID, string UserPW)
{
try
{
// do something
_credential.CookieCollection = browser.CookieCollection;
_credential.CookieContainer = browser.CookieContainer;
_credential.UserID = "test";
_credential.UserPW = "test";
}
catch (Exception err)
{
throw err;
}
}
}
// Credential.cs
public partial class Account
{
public class Credential
{
// Model
public CookieCollection CookieCollection { get; set; }
public CookieContainer CookieContainer { get; set; }
public string UserID { get; set; }
public string UserPW { get; set; }
}
}
// Form1.cs
public void ABC()
{
Account[] _account = new Account[2];
_account[0].Login("myID", "myPW");
Account.Credential _cred = _account[0].Credential; ---> I get an error.
}
But when I write a mothod call the Account class in array and call the sub class which is Credential, it gives me an error.
'Credential': cannot reference a type through an expression; try 'Account.Credential' instead.
Because, Login method is in Account Class I should have make an array of Account class. Not Credential class.
Does anyone know how to fix this?
As the error is trying to tell you, the Credential type is a part of the Account type; not any single Account instance.
It makes no sense to refer to the type myAccounts[42].Credential or mikesAccount.Credential.
If you want to get that user's credential, you'll need to refer to a field or property of the Account class.
You could write myAccounts[42]._credential, except that _credential is private, so that will give a different error.
You should make a public, probably-read-only, property.
This is happening because Account.Credential is an internal type to Account and isn't used like how you're using it. What code is attempting to do would be similar to trying
var str = String;
You need to initialize an Account.Credential. A simple was is to use new inside Account's ctor or the Login() method.
I noticed you're going to run into further problems with your code - if you want to access the Account.Credential reference declared inside Account, you'll need to expose it through a method or change the access modifier.
Ok, I've got this singleton-like web class which uses session to maintain state. I initially thought I was going to have to manipulate the session variables on each "set" so that the new values were updated in the session. However I tried using it as-is, and somehow, it remembers state.
For example, if run this code on one page:
UserContext.Current.User.FirstName = "Micah";
And run this code in a different browser tab, FirstName is displayed correctly:
Response.Write(UserContext.Current.User.FirstName);
Can someone tell me (prove) how this data is getting persisted in the session? Here is the class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
public class UserContext
{
private UserContext() { }
public static UserContext Current
{
get
{
if (System.Web.HttpContext.Current.Session["UserContext"] == null)
{
UserContext uc = new UserContext();
uc.User = new User();
System.Web.HttpContext.Current.Session["UserContext"] = uc;
}
return (UserContext)System.Web.HttpContext.Current.Session["UserContext"];
}
}
private string HospitalField;
public string Hospital
{
get { return HospitalField; }
set
{
HospitalField = value;
ContractField = null;
ModelType = null;
}
}
private string ContractField;
public string Contract
{
get { return ContractField; }
set
{
ContractField = value;
ModelType = string.Empty;
}
}
private string ModelTypeField;
public string ModelType
{
get { return ModelTypeField; }
set { ModelTypeField = value; }
}
private User UserField;
public User User
{
get { return UserField; }
set { UserField = value; }
}
public void DoSomething()
{
}
}
public class User
{
public int UserId { get; set; }
public string FirstName { get; set; }
}
I added this to a watch, and can see that the session variable is definitely being set somewhere:
(UserContext)System.Web.HttpContext.Current.Session["UserContext"];
As soon as a setter is called the Session var is immediately updated:
set
{
HospitalField = value; //<--- here
ContractField = null;
ModelType = null;
}
The UserContextinstance is saved in Session with this line:
System.Web.HttpContext.Current.Session["UserContext"] = uc;
It's not a singleton. The static property UserContext will attempt to retrieve a instance from Session, and if it doesn't find it, create a new instance and store it in Session.
UPDATE
I can see how the session var is retrieved, my confusion is around how the session var is set.
To add clarification following Micah's comment: the first time the static Current property is accessed, a new UserContext instance is created, its User property is populated with a new User instance, and the UserContext instance is stored in Session. Subsequent accesses to UserContext.Current (and hence UserContext.Current.User) in the same session are all accessing the same instance.
If it's still not clear I suggest stepping through with a debugger.
public static UserContext Current
{
get
{
// If Session does not yet contain a UserContext instance ...
if (System.Web.HttpContext.Current.Session["UserContext"] == null)
{
// ... then create and initialize a new UserContext instance ...
UserContext uc = new UserContext();
uc.User = new User();
// ... and store it in Session where it will be available for
// subsequent requests during the same session.
System.Web.HttpContext.Current.Session["UserContext"] = uc;
}
// By the time we get here, Session contains a UserContext instance,
// so return it.
return (UserContext)System.Web.HttpContext.Current.Session["UserContext"];
}
}
Joe is right. Your usage is: UserContext.Current.User.FirstName
In the getter of UserContext.Current, you're getting back a reference to a piece of memory that lives inside the session object within asp.net. Using any of the setters should/would change that memory and if you inspect the session object either in the debugger or on subsequent lines of code, you should see the same data that you set with your setters.
And run this code in a different
browser tab, FirstName is displayed
correctly:
You are saving it in the session. Opening a new tab can use the same session information as the other tab (I'm not certain about all browsers). Try opening a new browser window (not just a tab), and see what happens.