Cache my static data in server for all user C# - c#

I want to cache some static data in server. if any user request for same data cache should return that.
if i go with HttpContext.cache, it will vary by user. please help me how to do that in c#?
What I have tried:
HttpContext.Cache.Insert(cacheKey, Sonarresult, null, DateTime.Now.AddSeconds(Timeduration), Cache.NoSlidingExpiration);
i tried this but for all users will store into cache. i dont want that. first user only has to store it.

Using the application cache just like you would a session variable can do the trick for you.
e.g.
// get
string message = Application["somemessage"].ToString();
will be the same for all users.
to elaborate further, be careful where on your code you set the value for application variables because once they change, they will change for all.
// set
Application["somemessage"] = "your message";
Global.asax would be a could place to set the value of Application variables if they never change:
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
// here we set the value every time the application starts
Application["somemessage"] = "your message";
// the following line will get the SiteName from the web.config setting section
Application["SiteName"] = ConfigurationManager.AppSettings["SiteName"].ToString();
}

You can use application cache to do this.
void Application_Start ()
{
_cache = Context.Cache;
_cache.Insert ("mycahce", mystaticvariabledata, null,
Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
CacheItemPriority.Default,null);
}

Related

Save and retrieve Wrong Value From Json Object Items to IShared Preference in Xamarin.Android (Always Returns Logout Value)

I am developing a login application which save username and password using Shared Preferences in Xamarin Android (C#). Firstly, I get the username and password value from web service and then I check the value. If in my local db (sqlite) doesn't have the value so, I update the data with the newest one from web service. After that, I store the user ID by using my custom sqlite function to get the user ID with username and password.
So far, I can parse the Json Object from my web service and assign them into variables. But, I found something strange that, my parsed json object item can't be saved in my shared preferences. I've been 3 days searching and researching from internet but, I didn't find anything. I almost give up, guys. Would you like to help me? I would appreciate the helps.
Here what I did to my app.
I made utilities folder which save my essentials class. I made LoginSession class which save property of user now.
in my main activity
private void MyBtnLogin(object aSender, System.EventArgs e)
{
try
{
System.Net.Http.HttpClient client= new System.Net.Http.HttpClient();
System.Threading.Tasks.Task.Run(async () =>
{
string response = await _httpClient.GetStringAsync($"http://yourjson.com/{fix_email_value}");
JObject parsedObject = JObject.Parse(response);
int userID = parsedObject .Value<int>("ID");
string userEmail = _parsedResponseObject.Value<string>("Email");
string userPassword = _parsedResponseObject.Value<string>("Password");
List<User> lists= User.GetUserList(userID);
User updatedvalue= (from a in lists where a.Email == userEmail && a.Password == userPassword select a).FirstOrDefault();
if (updatedvalue== null)
{
updatedvalue= new User();
updatedvalue.ID = userID;
updatedvalue.Email = userEmail;
updatedvalue.Password = userPassword;
updatedvalue.StoreOrChange();
RunOnUiThread(() =>
{
SharedPref.UserIDNow= userID;
LoginSession.UserNow= User.GetID(userID);
});
} }
});
StartActivity(typeof(NextPage));
Finish();
}
and I retrieve the value in the next activity using SharedPref.UserIDNow to retrieve the user ID. I put the SharedPref.UserIDNow inside my static function to get current User ID
What am i missing? Everytime when I launch and login, after login the app closed like log out! and the value returns -22. Btw, -22 is a default value of my shared preference. I think it must be the ID of the User. Please help me :(
I test with your code , it works with no problem .
Some suggestions to troubleshoot .
Debug your code (add breakpoint) to check if SharedPref.UserIDNow= userID; has been executed , and also remove RunOnUiThread method ,you don't need to wrap code into it unless UI elements gets changed .
Use default SharedPreferences ,change preference as
private static ISharedPreferences preference = PreferenceManager.GetDefaultSharedPreferences(Application.Context);
Use Commit instead of Apply method on ISharedPreferencesEditor,Apply is asynchronous method which means if you read value too early ,you would get default value at that time .

Setting unique Session variables at Application level

I have a Web Forms application that does not have a login page. Technically a user can access any page directly. However, I need to be able to identify who the logged-in user is on each page. I don't want to add code to each page. I would rather set a unique session variable at the start of the session. For this I added into my Global.asax.cs the following:
protected void Session_Start(object sender, EventArgs e)
{
if (Session["LoggedInUser"] == null)
{
string networkId = HttpContext.Current.User.Identity.Name;
using (UnitOfWork unit = new UnitOfWork())
{
if (networkId.IndexOf("HLM\\") > -1) { networkId = networkId.Substring(4, networkId.Length - 4); }
loggedInUser = unit.PersonRepository.GetByNetworkID(networkId);
Session["LoggedInUser"] = loggedInUser;
}
}
else
{
loggedInUser = (Person)Session["LoggedInUser"];
}
}
I now see that it sets the loggedInUser to whatever user last created a session. Meaning, if Mike goes to the site he will see data that represents him as the loggedInUser. However, if Kate goes to the site after him, Mike will now see Kate's data. Basically, the last one in overwrites everyone's settings and Session_Start is overwriting the value for loggedInUser for all active Sessions.
Based on this link: https://books.google.com/books?id=nQkyi4i0te0C&pg=PA202&lpg=PA202&dq=C%23+set+unique+session+variable+in+global.asax&source=bl&ots=GV9nlEUzE5&sig=E4TT3NDbjp1GwEehgU3pLXKdvr0&hl=en&sa=X&ved=0ahUKEwiU9f322tvSAhVF7yYKHYaXCtwQ6AEITzAI#v=onepage&q=C%23%20set%20unique%20session%20variable%20in%20global.asax&f=false
It reads that I should be able to set unique session variables for each new session but my results don't show that.
Am I misunderstanding how this works? I need to set a unique session value at the beginning of each session for each user.
I found the issue. The Session_Start is doing what is supposed to at a unique session level. The way I was referencing the session value was all wrong. Instead of accessing the session value I was actually doing:
Person loggedInUser = Global.loggedInUser;
Which makes sense that it was returning the latest user to start a session.

Where to store user data after login with WebForms

I'm developing a WebForms web application with VS2010 in C#. I use my custom login approach to authenticate users and I don't want to use Membership framework. After user login I want to store user data as userId, username, surname, email, etc., so I can access them during the user session in all pages.
How can I do that? I don't wanna store user data in the UserData property of the FormsAuthenticationTicket.
I found this approach: Should I store user data in session or use a custom profile provider?, but I don't understand how to implement it.
I have some question:
1)in my login page to authenticate user after check credentials on db I use : FormsAuthentication.SetAuthCookie(txtUserName.Value, true); now in my default page I have:
FormsAuthenticationTicket ticket = ((FormsIdentity)(User.Identity)).Ticket; and I use ticket.Name to show username. is it correct? why do you talk about thread using Thread.CurrentPrincipal.Identity.Name ?
2) I have this code in global.asax file to read user roles and store thems into HttpContext:
void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (Request.IsAuthenticated) {
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLConnStr"].ConnectionString);
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT Gruppi.Name FROM Ruoli INNER JOIN Gruppi ON Ruoli.GroupID = Gruppi.GroupID INNER JOIN Utenti ON Ruoli.UserID = Utenti.UserID AND Utenti.Username=#UserName", conn);
cmd.Parameters.AddWithValue("#UserName", User.Identity.Name);
SqlDataReader reader = cmd.ExecuteReader();
ArrayList rolelist = new ArrayList();
while (reader.Read()){
rolelist.Add(reader["Name"]);
}
// roleList.Add(reader("Name"))
string[] roleListArray = (string[])rolelist.ToArray(typeof(string));
HttpContext.Current.User = new GenericPrincipal(User.Identity, roleListArray);
reader.Close();
conn.Close();
}
}
can I store user data into session as you wrote from my global.asax file rather then login.aspx page?
In the interest of easier debugging, I suggest using the Session Facade design pattern, described here, that will allow you to store the current user's data using the HttpContext.Current.Session object in a more organized fashion.
For instance, there would be a file (e.g., SessionFacade.cs) that is responsible for handling the values passed to/from the Session; in your case, it might look like:
public static class SessionFacade
{
public static int UserId
{
get {
if (HttpContext.Current.Session["UserId"] == null)
HttpContext.Current.Session["UserId"] = 0;
return (int)HttpContext.Current.Session["UserId"];
}
set {
HttpContext.Current.Session["UserId"] = value;
}
}
// ... and so on for your other variables
}
Then, somewhere else in your code, once you check that credentials are okay, you can do...
if (credentialsAreOk) {
SessionFacade.UserId = /* insert ID here */
// ...
}
...instead of manually assigning values to the Session object. This ensures your variables in Session are of the correct type, and will be easier to track while debugging. Then, to get the UserId from anywhere in your program, it's just SessionFacade.UserId.
(yes that snippet was from Eduard's answer; you should still look into that answer as it is informative as to how WebForms work; just keep in mind that calling the Session object manually in your code can be quite messy and that the Session Facade makes that process cleaner)
In case that by "web application by VS2010 in C#" you're talking about ASP.NET (MVC or Classic) and by "custom login approach" you're referring to FormsAuthentication then all you need to do is to store your later needed information at login time, onto the Session object.
Let's say you're using ASP.NET Classic and you have a login page
which has 2 inputs for Username and Password and a submit button entitled "Login"
In the button's (server side) OnClick event handler you should do something like this:
public partial class Login : System.Web.UI.Page {
protected void Page_Load(object sender, EventArgs e) {
}
private bool CheckUserPass(string username, string password) {
// access DB or some other form of storage service
return true;
}
protected void buttonLogin_Click(object sender, EventArgs e) {
bool credentialsAreOk = this.CheckUserPass(
this.textBoxUsername.Text,
this.textBoxPassword.Text
);
if (credentialsAreOk) {
this.Session["EMAIL_ADDRESS"] = "SomeEmail#SomeEmailProvider.com";
this.Session["OTHER_INFORMATION_KEY"] = "Some other stuff which you have access to during the login process";
this.Session["TIME_OF_LOGIN"] = DateTime.UtcNow;
FormsAuthentication.RedirectFromLoginPage(this.textBoxUsername.Text, createPersistentCookie: false);
}
}
}
So, in short, if you're using FormsAuthentication, then the username can be stored onto the session in the same way you're telling the FormsAuthentication system that current session should be transformed from non-authenticated to authenticated:
FormsAuthentication.RedirectFromLoginPage(this.textBoxUsername.Text, createPersistentCookie: false);
whereas other information can be placed on the Session object (just like you would add key value pairs to a Dictionary):
this.Session["TIME_OF_LOGIN"] = DateTime.UtcNow;
While it is obvious how you could later access that same information (for the respective user):
DateTime whenDidILogin = (DateTime) this.Session["TIME_OF_LOGIN"];
// this line of code can be used in any other page
// at any later time - it's like you have a global set of variables
// which exist for each and every distinct session you might have
it is maybe important to mention that the username (if not placed explicitly onto the Session object like the other examples) can be accessed by means of the Thread.CurrentPrincipal static property like so:
using System.Threading;
public void SomeWhereInYourApp() {
bool wasIAuthenticated = Thread.CurrentPrincipal.Identity.IsAuthenticated;
string whatIsMyUsername = Thread.CurrentPrincipal.Identity.Name;
// do something with that information
}
Membership provider helps you to store data and also for authentication purpose. Something like this:-
Session["UserName"] = Membership.GetUser().UserName

How can I keep my variable all the time without global variables?

I have two GridViews. I've got method GetGeneralDiagnosis which returns a list of all diagnosis:
CODE DIAGNOSIS
F50 Eating disorders
F51 Nonorganic sleep disorders
and method GetSpecificDiagnosis which returns more specific list:
CODE DIAGNOSIS
F50.0 Anorexia nervosa
F50.1 Atypical anorexia nervosa
F51.0 Nonorganic insomnia
F51.1 Nonorganic hypersomnia
Now I've got method which bind SPECIFIC DIAGNOSIS to second GridView according to GENERAL DIAGNOSIS from first GridView.
protected void gvGeneralDiagnosis_SelectedIndexChanged(object sender, EventArgs e)
{
string generalDiagnosis = gvGeneralDiagnosis.DataKeys[gvGeneralDiagnosis.SelectedIndex].Values["ICD10Code"].ToString();
var ICD10 = Visit.GetSpecificDiagnosis(); // here I'm getting data from database
gvSpecificDiagnosis.DataSource = ICD10.Where(i => i.ICD10Code.Contains(generalDiagnosis)).Select(i => new { i.ICD10Name, i.ICD10Code });
gvSpecificDiagnosis.DataBind();
}
I don't want to connect to database each time selected index is changed.
How can i get my list var ICD10 = Visit.GetSpecificDiagnosis() only once? I heard that global variables are very bad idea, so how can I do that in another way?
You can use a private member variable. This one "lives" as long as the class containing it lives. Wrap it with a property to access it and automatically read it from the database, if necessary.
private TypeOfICD10 _icd10;
private TypeOfICD10 ICD10
{
get
{
if (_icd10 == null) { // Get from database.
_icd10 = Visit.GetSpecificDiagnosis();
}
return _icd10;
}
}
Now you can use it like this and it will be read from the db only at the first call
protected void gvGeneralDiagnosis_SelectedIndexChanged(object sender, EventArgs e)
{
string generalDiagnosis = gvGeneralDiagnosis.DataKeys[gvGeneralDiagnosis.SelectedIndex].Values["ICD10Name"].ToString();
gvSpecificDiagnosis.DataSource = ICD10
.Where(i => i.ICD10Code.Contains(generalDiagnosis))
.Select(i => new { i.ICD10Name, i.ICD10Code });
gvSpecificDiagnosis.DataBind();
}
You can have your Visit class cache the returned data.
When GetSpecificDiagnosis is called, it will check whether this data was already retrieved from the database, and return it if it was. If it wasn't, it'll retrieve it from the database and save it to its cache.
One thing you should pay attention to is whether this data is static (i.e. never changes throughout the application's lifetime) or is it dynamic. In the first case, you won't have to do any special handling, but if it's the latter, you'll have to invalidate the cache one the information in the database has changed.
I recommend you to have a look here to see how to get started with caching in ASP.NET.
I don't know much about the Visist class from your question but why not cache ICD10 this way you will be using the cached object and the Database call will made only if the Cache Key ICD10 has a value of null
Example :
if(Cache["ICD10"] == null)
{
var ICD10 = Visit.GetSpecificDiagnosis();
Cache["ICD10"] = ICD10;
}
else
{
var ICD10 = Cache["ICD10"];
}

Check Validity for a QueryString using Entity Framework

I use C# Asp.Net and EF 4.
I have a scenario like MasterPage and DetailsPage.
So from my MasterPage I pass a variable as a QeryString to the DetailsPage, the DetailsPage will show up details for a specifc item in my DataBase.
I need to check the validity for my QueryString, in details I need:
Check if is Null, Empty or White Spaces.
Check if is NOT of type INT (just numbers not any letters).
Check if the Object NOT exists in my DB.
In case if Check result True, I will redirect the User.
At the moment I wrote this script. It is works but I would like to know if you know a better approch/code to solve this.
Also I would like to know if make sense to have this logic on every time the page Load, or would be enought us just on !Page.IsPostBack.
Thanks once again for your support guys!
protected void Page_Load(object sender, EventArgs e)
{
#region Logic Check Query String.
// Query String is Null or Empty.
if (string.IsNullOrWhiteSpace(ImageIdFromUrl))
RedirectToPage();
// Query String is not valid Type of INT.
int ImageId;
bool isInt = Int32.TryParse(ImageIdFromUrl, out ImageId);
if (isInt)
{
// Check if a valid Object request exist in Data Source.
using (CmsConnectionStringEntityDataModel context = new CmsConnectionStringEntityDataModel())
{
if (!context.CmsImagesContents.Any(x => x.ImageContentId == ImageId))
{
RedirectToPage();
}
}
}
else
RedirectToPage();
#endregion
}
You don't need to check it on every postback, only on a full page load. The query string is not sent to the server on postbacks.
I suggest you move all the query string validation logic to separate functions.

Categories

Resources