I'm new to ASP.NET and C#. I have a web form with a static list like this:
private static List<Book> listBook = new List<Book>();
Since the server destroys everything after sending back to client plain HTML, so why whenever I add a new book to the listBook(via checkboxes), it stores info across post back(in a single page)? First I thought it was viewstate but clearly viewstate only stores ASP.NET Control info. Please help me, Thanks in advance!
public partial class TestSortBook : System.Web.UI.Page
{
private static OBMDbContext context = new OBMDbContext();
BookBL bookBL = new BookBL(context);
GenreBL genreBL = new GenreBL(context);
private static List<Genre> listGenre = new List<Genre>();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
List<Book> listBook = bookBL.FindAllBooks();
PopulateGridView(listBook);
//PopulateGridView(bookBL.SortBookByPriceAscend(listBook) );
PopulateListView(genreBL.FindAllGenres());
}
}
protected void CheckBox1_CheckedChanged(object sender, EventArgs e)
{
CheckBox cb = (CheckBox)sender;
HiddenField hf = (HiddenField)cb.FindControl("HiddenField1");
int genreID = Convert.ToInt16(hf.Value);
listGenre.Add(genreBL.FindGenre(genreID));
Response.Write("Nothing");
}
}
Let me explain the code above. There's a listview which has a checkbox and a hidden field in each listview item. Whenever I click a checkbox, it add a new genre to my listGenre and save info across postback.
Since the server destroys everything after sending back to client plain HTML
That's not true at all. Each postback results in a new class instance being created to handle the response for that request. Since you have a static field, its data will persist between requests.
That said, you cannot rely on every single request having access to the same variable with this method; if you have multiple web servers handling responses, they would each have their own static variable. This makes static fields useful for caching content in some instances, but not as the canonical source of data (generally speaking).
where does the static variable store info across postback?
In memory, as any other variable.
You must understand that each page on Asp.net relies in a class, it's not like php or other scripted languages, your site is a program (technically speaking it's an assembly loaded in an AppDomain under the IIS process :P), because that you have an application pool on which you configure how that "program" will run (basically each pool is an isolated AppDomain), so, while the server doesn't purges these application pools your site pages classes will be alive , and thus any static variable will persist on memory.
Have you considered using the Browser Local storage to store stuff for each user.
depending on what you are storing and how you plan to use it, it might be the best option
Related
Here's the deal: I have a site where multiple people will be sharing the same account and should each be able to be on a page that uploads files and keeps a list of the files they've uploaded that session. The controller for the file uploading page looks like
public class FileUploadController : Controller
{
// ...
private List<ThreePartKey> uploadedFiles = new List<ThreePartKey> ();
public ActionResult Index ( )
{
// ...
}
[HttpPost]
public ActionResult Index (HttpPostedFileBase file)
{
// ...
if (!errorOccured)
{
uploadedFiles.Add(new ThreePartKey { orgname = selectedOrgName, catname = selectedCatName, filename = fileNameNoExtension, fullfilepath = newFileUrlPathAndName });
}
// ...
}
and the problem is that uploadedFiles keeps getting re-initialized whenever [HttpPost] public ActionResult Index (HttpPostedFileBase file) is called, meaning the user's list of uploaded files only shows the last uploaded one. So I instead tried
private static List<ThreePartKey> uploadedFiles = new List<ThreePartKey> ();
and that screwed up everything because all the signed-in users are sharing the same list.
Is there any easy way to do what I'm trying to do?
Controllers are instantiated and destroyed on every request. If you want to persist information in a webserver it is strongly advised to use a permanent backing store such as a database.
You can use static state in ASP.NET applications (WebForms, MVC, OWIN, etc) however this is only recommended for caching for performance. It cannot be relied upon because static state is only local to the current AppDomain in the current Application Pool (w3wp.exe instance) - if your website is run in multiple pools or appdomains, or if your application is restarted (or killed due to inactivity) then the stored state is lost.
On option is to provide a 'session' code/id with each request. When user first connects to your site, they are given a session-code (I use 'code' to indicate it has nothing to do with what we would normally call 'session').
Every link has that session-code as part of the url and every post includes the session-code. Then your upload cache can be:
private static ILookup<int, ThreePartKey> uploadedFiles;
(or dictionary if you prefer)
private static IDictionary<int, IList<ThreePartKey>> uploadedFiles;
Depends on the size of the rest of your site if this is workable or not - in most cases probably not as described... but could be managed, eg use the IP address as the 'code' or if you're using AnglurJS or single page application.
As pointed out, any static/singleton cache will still be lost if the app pool is reset, eg via the inactivity timeout setting in IIS.
Another option is to persist the files in subfolders based on the user's IP address.
You've only stipulated that they all use the same login, not how the files are stored etc, so maybe this would work for you.
I am testing to build a asp.net web application.
What I have is 3 web pages:
Default.aspx;
Home.aspx;
ThirdPage.aspx;
When user submits login data to Default.aspx, I retrieve user information from db, put it in a class and add it to Context like this
HttpContext.Current.Items.Add("UserData", userData);
Then I use Server.Transfer to send the request to Home.aspx.
On Home.aspx, I have a link which points to ThirdPage.aspx. I click on this link and hoped that user information would be available here as well but it is not. Where as I was hoping to retain the userdata class across the user session across all pages in my web application until users session is expired .
Can some one please guide?
It is possibly a beginner question so please be kind.
Thanks
Check ASP.NET Session State Overview
Usage:
Session["UserData"] = userData;
I am unsure what the exact problem may be but I have some solutions that might work. If I am not mistaken you are trying to get user information over a couple of pages?
Here are some ways to get that done:
Repeat the code you did on the first page that transfers the data to
the second page and adapt it so it will work from the second to the
third. This might work but I won't recommend because having to reuse
and adapt the code each time you create a new page.
The better one I think is to write your information to an XML file and deleting the file when the session expires.
You can find how to write it here and reading it here.
But my personal favorite is to have a static Class. Static classes can be acces from anywhere. As shown on the page here.
public static class Globals
{
public static String name;
public static int age;
public void SetName(){...}
public void SetAge(){...}
public String GetName(){...}
public int GetName(){...}
}
Just make it a mutable class (You can change the variables using functions) and it should be easy to get the user information across pages.
Using JSON to save and load here are c# functions:
public void SaveInfo(User user){
//Convert to Json
string json = JsonConvert.SerializeObject(user, Formatting.Indented);
//Write to file, you will have to create a file serverside if you want
//if you have a
File.WriteAllText(#"location.json", json);
}
public void LoadUser(){
using (StreamReader r = new StreamReader("Location.json"))
{
string json = r.ReadToEnd();
List items = JsonConvert.DeserializeObject>(json);
}
I am making a project using WebServices in C#. I wanted to ask you, how can I give a value to a variable from Client to a Web Service?
For example:
In the web service I have a variable and two Methods, getVariable() and setVariable(bool a);
bool var = false;
[WebMethod]
public void setVariable(bool a)
{
var = a;
}
[WebMethod]
public bool getVariable()
{
return var;
}
This is how my web service looks (it's simple because I am learning).
My client:
//In the client I added the web service as a Service Reference and added this code:
ServiceReference.ServiceSoapClient obj = new ServiceReference.ServiceSoapClient();
private void Form_Load(object sender, EventArgs e)
{
obj.setVariable(true);
label1.Text = obj.getVariable().ToString();
}
And when I load my form, the label1.Text isn't equal with "True" but with "False"!! Which means that it didn't execute this code: obj.setVariable(true);
My professor said in the class something that WebService are now "full...." (but I couldn't hear it well), he said you have to find a way to make WebServices "ful..."
Can someone help me ?
Web services are stateless by default, which means that they don't retain state between calls. So a value set in one call won't be available for usage by the next call.
If you need a stateful service, there are several ways to go. this is probably the simplest.
It sounds like you are doing this for learning purposes, in which case I suggest reading up on why it is not a good practice to develop using stateful services. Try this one for starters.
Since web services are stateless you can't do what you are trying to do.
Although you have only one client instance, for each call a server-side instance gets created. That means that in the first call you set the variable on an object, which then goes out of scope (since it's tied to that request). When you do make the second call, a new instance of your service gets created and this new instance obviously has no knowledge of the previous one.
If you want to do something like that you need the save the state. This can be done in various ways:
Save the value in the Application object (HttpContext.Current.Application("myvar") = a)
Save it in session state (you need to add an attribute to the service class to enable session state, then you do the same as with the Application but accessing HttpContext.Current.Session
Save it in a database
Save it in a file
...
#I4V - Thanks for your comment on my post.
I just added static before the bool variables and it worked.
I have a website that, in order to work properly, needs to have a XML file appended to all its URLs, let's say the file is called module-1.xml.
In order to keep those URls clean, I wrote a IHttpModule's that uses the HttpContext.Current.RewritePath to do the appending job inside the OnBeginRequest event.
The IHttpModule looks pretty simple and works:
public void OnBeginRequest(Object s, EventArgs e)
{
string url = HttpContext.Current.Request.Url.AbsolutePath;
if (url.EndsWith(".aspx"))
HttpContext.Current.RewritePath(url + "?module-1.xml");
}
Now, I wanted to use the session variable to detect when a user decides to switch the website from model-1.xml to model-2.xml and have my code changed as follow:
public void OnBeginRequest(Object s, EventArgs e)
{
string url = HttpContext.Current.Request.Url.AbsolutePath;
if (url.EndsWith(".aspx"))
{
if (HttpContext.Current.Session["CurrentMode"] == "1")
HttpContext.Current.RewritePath(url + "?module-1.xml");
else if(HttpContext.Current.Session["CurrentMode"] == "2")
HttpContext.Current.RewritePath(url + "?module-2.xml");
}
}
From what I have found, the session can be accessed inside a module but
not from inside the OnBeginRequest event which is the only event where HttpContext.Current.RewritePath can be made functional (at least from all the testing I have been doing).
Is my assumption correct? And if it is, what alternative could I use? Create a custom Session variable? Should I read from a txt file or from a DB in order to know what module the user is looking at? How could I keep track of a user from within the module?
It depends on the security required by your application. If you don't care about a malicious user being able to change the value, just store the module name in a cookie. If you do, you could store a securely generated identifier in a cookie, and look that up in a database to get the value you need to use.
Get rid of the module completely. You are only attaching it to aspx pages, so there is no need for that to be in the URL. Instead just create a base page for your project pages to inherit from:
public class Solution.Web.UI.Page : System.Web.UI.Page
{
public string CurrentMode
{
get { return String.Compare(Session["CurrentMod"].ToString(), "1") == 0) ? "module-1.xml" : "module-2.xml"; }
}
}
That way you can simply access it on your pages without the overhead of that module or the risk of putting that info in a cookie.
I have a code behind file of an aspx file that looks like this:
public partial class Pages_MyPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
.....
}
protected int MyMethod()
{
.....
}
[WebMethod]
public static int MyPageMethod()
{
int x = MyMethod();
return x;
}
}
When I'm sending an ajax POST to MyPageMethod, I can't access MyMethod. What's the way around this issue.
Thanks for your suggestions.
MyMethod will also need to be static.
Think about what your trying to do here -
MyMethod belongs to a specific instance of a class.
MyPageMethod belongs to the class itself.
If your running code inside MyPageMethod, how could you possibly know how to call methods on some other instance of the object. The instance methods may as well not exist at that point in code.
If you are trying to mutate some portion of the page's data from javascript, you have a deep misunderstanding of how asp.net pages work.
At the point javascript is running in the browser, your page object is gone. The server finished the page load and discarded it. On the next post back it will create a new instance, and run through the page life cycle once again.
If you need to access page level state, you will have to store it in a place that is acceptable between post backs, the Session object for instance, with System.Web.HttpContext.Current
WebMethods are static methods because they don't get a full Page.
They can only call other static methods