protected void Page_Load(object sender, EventArgs e)
{Label1.Text = DateTime.Now.ToString();}
If, after I compiled this newly created application, browser B1 is
first to request Cache.aspx, then the time displayed on received page
is 10.16:20.
If, after say 10 seconds, I refresh B1’s Cache.aspx( by clicking a
button to cause a postback), then time 10.16.30 will show up, and on
all subsequent postbacks 10.16.30 will always be displayed ( until 1
hour elapses ).
If few minutes after B1 first requested Cache.aspx, browser B2 also
requests the same page, then upon receiving the page for the first
time, B2’s Cache.aspx will display time 10.16.20, and on all
subsequent B2’s postbacks time 10.16:30 will be displayed instead.
A) So it appears that Asp.net generates two cached versions of
Cache.aspx ( thus code is executed twice ), one cached page is given
to browsers that request Cache.aspx for the first time, and second
cached page is given to browsers which only refresh their Cache.aspx?
B) Since my book never mentioned such a behavior, I’m wondering if you
get the same behavior or is my Net environment again “unique”?
C) Creating two copies of same page ( thus executing the code twice )
seems like a waste of time, so why does Asp.Net operate like that –
there must be some reasoning/benefits behind it?
thank you
A complete guess, but presumably the cache is isolated by the overall request (query string args, etc)... even though the "none" turns off the key/value pairs, presumably a "GET" is simply still counted as different to a "POST"???
Try using simple links (<a href...> etc) rather than ASP.NET buttons.
if i try
if (ispostback)
begin
response.cache.setcachebility(nocache)
end
then the button click updates the label every time.
Related
I have a session variable which is used to store a datatable (which changes depending on how the user wishes to add / remove items (data items in the datatable).
At the last page of the whole web application, I have a submit page to allow the user to submit the selected items in the datatable.
Because I think session variables may expire if the page is left open too long, and to prevent errors arising from expired variables, at the page_load function's !IsPostBack I assigned the session variable to a viewstate variable (so the data will be stored in the page's viewstate and not expire).
if(!IsPostBack){ ViewState["myDataTable"] = Session["myDataTable"]}
1) Is this the standard practice and are there any implications / errors when assigning a session variable to a viewstate?
2) After calling ViewState["myDataTable"] = Session["myDataTable"], is it ok to do Session["myDataTable"] = null ?
It really depends on the kind and size of data you have there.
It is key to remember that you need to treat anything you send to the client as compromised data. Another way to put it, if you'd be ok with an user having available a form that allows them to input every single bit of that data, only then it is ok.
All said, the viewstate is normally signed, but history as proven is a good idea to follow that general security advice.
As for the size, you need to keep an eye on the amount of data being exchanged on each request.
Last about clearing that session value afterwards, asp.net mvc does similar for what it calls TempData. The scenario for its use: pass some data from one page to the next on non post scenarios + and when you don't want it in the query string.
Yes, you can do it. but viewstate tends to slow the page loading due to extra overhead. If your dataset is small it is ok, but if its bigger then look for other alternatives.
How ever I will recommend not to go with this method[security problem,slow etc.], instead device a way so that session dosent expire if any page is open?? how?? use jquery/ajax to maintain a connection with server at regular interval.
If you want to go some further implement sql session. It will be the best.
Hope these info help you.
I'm trying to retrieve an image from a HTTP Handler.
An issue which I'm having is trying to make it so that only the application can access the image, I've tried editing the anonymous IIS authentication to allow the application pool identity but this still lets users through.
Here's an example:
ASPX page makes a call to the handler (picService.ashx?id=1) passing in an ID via query string
HTTP Handler sends back image
The image source is Services/picService.ashx?id=1
This all works fine. Now if a user wanted to go and visit picService.ashx and type in any old ID, it would return the image which correlates to that ID. I'm working with sensitive information so this isn't acceptable.
I've had a look at HTTP Forbidden handlers but I'm not sure whether I'm going down the right route.
I've also tried returning the image in the ASPX page but you can't do this due to the Image control needing a URL.
How can I return an image from a database and have the source of the image be secure?
Should I be doing this a different way? Or am I on the right track (http forbidden)?
A technique I have used in the past is to have the page (step 1) create a GUID, and register a cache item keyed by the GUID that has the actual image URL in the object. The page constructs the url for the handler, using the GUID and passes to the handler
The handler (step 2) then knows to go to cache to get the actual value and return the content.
This way you only expose the temporary "magic" value. Its definitely obfuscation and not a substitute for proper security.
As an example (from memory, syntax may be off a bit)
In the aspx or caller
string keyValue = Guid.NewGuid().ToString();
int yourImageID = 5;
Cache.Add(keyValue, yourImageID) //expire in 5 or 10 seconds
string url = "Handler.ashx?imgID=" + HttpUtility.UrlEncode(keyValue);
Response.Redirect(url, false);
In your handler (I use ashx mostly, choose whatever suits your need)
string key = HttpUtility.UrlDecode(context.Request.QueryString.Get("imgID"));
int yourImageID = (int) context.Cache.Get(key);
//get your image from the db and return the content
Again, just because I used a guid doesn't mean you have to, but if you are trying to obfuscate the IDentity, then choose something that does not correlate to the IDentity.
The way you word your question there is no way to get it 100% secure. So what trade-offs are you willing to allow and what are you not?
What exactly are you trying to prevent? Only one user not seeing another user's image? Or prevent right-click, save image as as well?
One idea that comes to mind is combine the user's ip address with the id of the image, hash that, throw it in a cache (or use a guid as a key to look up those values). Maybe remove it from the cache once that hash is used, therefore only allow the image to be loaded once by one ip per page it is supposed to be on.
You should be able to throw the mapping between a generated ID and real into the session, or HttpRuntime.Cache.Insert(cacheName, cachedValue) Database is probably not the best answer, they are small amounts of data, and you can set the expiration time to a small value, so unless you have millions of users at a time...
Using a Flash control to load the image would be secure in terms of can't right-click save image as. Also probably could encrypt the stream, or split apart the image headers or something if you're worried about someone intercepting the image stream. They could still get a url to the image, but your flash control could use special headers which would be difficult for the average user to ever figure out.
First and foremost you have to know what do you consider as OK to show photo . What is your authentication parameter. Like if user is allow to see the pic when is authenticated , check the same in , ashx page before allowing it to see. Because calling inside the html as src or putting the same in browser does not make any difference for server . So you need to check some validation in case user is not at all supposed to see in any way directly or in directly
Store the URL and parameter in Session state and access the Session in the HttpHandler. To do this you would need to implemement the IRequiresSessionState in your handler:
Problem with HttpHandler and session state
Getting Session State in HttpHandlers (ASHX files)
I've got this piece of caching code
public static ICollection<Messages> GetMessages()
{
if (System.Web.HttpContext.Current.Cache["GetMessages_" + user_id] == null)
{
using (DataContext db = new DataContext())
{
var msgs = (from m in db.Messages
where m.user_id == user_id
&& m.date_deleted == null
select m).ToList();
System.Web.HttpContext.Current.Cache.Insert(
"GetMessages_" + user_id, msgs, null,
DateTime.Now.AddMinutes(5), TimeSpan.Zero);
}
}
return System.Web.HttpContext.Current.Cache["GetMessages_" + user_id]
as ICollection<Messages>;
}
The first time it runs, it pulls the data from a SQL table, and takes about 1500 ms. Every subsequent call takes about 600ms. The collection i'm testing on currently contains just 3 objects, each with minimal data (a string, 3 datetime fields, 3 bools and 5 ints)
Is this normal? loading a page with this tiny amount of data on it takes almost 2 seconds, every single time.
[FYI this is just running on a dev machine, not a fully fledged web server. data is being pulled from a remote server but that should only affect the initial page load]
Please remember that when you create first Context in EF code first approach - EF has to rebuild model from metadata which slow down first invokation.
As noted by HackedByChinese, this was running in the VS development web server which of course slowed things down. However, I did find that my programming style was lending itself to very slow load times.
I used the method above to load a cached collection of messages, and also similar methods to pull back other entities from the database. One such item was a 'Settings' object.
On the settings page, I would call the function each time I wanted to return a property. For instance Cache.GetSettings().username, then Cache.GetSettings().useremail etc. I assumed that this would make the app run a little faster, as it's retrieving the object from the cache each time, without needing to access the database. But obviously, cache is not as fast as memory. Each call was taking about half a second (on the local server) and maybe .1s or .2s on the remote server. I realised if I set this to a variable...
var settings = Cache.GetSettings();
and referenced that instead, load times dropped significantly. There was a single 0.5s load at this line, and then every subsequent reference to settings took no time at all.
So to sum up, yes, cache can be slow, but only if you use it in a stupid manner like I did!
I stucked at a condition , where i need to share values between the pages. I want to share value from Codebehind via little or no javascript. I already have a question here on SO , but using JS. Still did'nt got any result so another approach i am asking.
So I want to know can i pass any .net object in query string. SO that i can unbox it on other end conveniently.
Update
Or is there any JavaScript approach, by passing it to windows modal dialog. or something like that.
What I am doing
What i was doing is that on my parent page load. I am extracting the properties from my class that has values fetched from db. and put it in a Session["mySession"]. Some thing like this.
Session["mySession"] = myClass.myStatus which is List<int>;
Now on one my event that checkbox click event from client side, i am opening a popup. and on its page load, extracting the list and filling the checkbox list on the child page.
Now from here user can modify its selection and close this page. Close is done via a button called save , on which i am iterating through the checked items and again sending it in Session["mySession"].
But the problem is here , when ever i again click on radio button to view the updated values , it displays the previous one. That is , If my total count of list is 3 from the db, and after modification it is 1. After reopening it still displays 3 instead of 1.
Yes, you could but you would have to serialize that value so that it could be encoded as a string. I think a much better approach would be to put the object in session rather than on the URL.
I would so something like this.
var stringNumbers = intNumbers.Select(i => i.ToString()).ToArray();
var qsValue = string.Join(",", stringNumbers);
Request.Redirect("Page.aspx?numbers=" + sqValue);
Keep in mind that if there are too many numbers the query string is not the best option. Also remember that anyone can see the query string so if this data needs to be secure do not use the query string. Keep in mind the suggestions of other posters.
Note
If you are using .NET 4 you can simplify the above code:
var qsValue = string.Join(",", intNumbers);
Make the object serializable and store it in an out-of-process session.
All pages on your web application will then be able to access the object.
you could serialize it and make it printable but you shouldn't
really, you shouldn't
The specification does not dictate a minimum or maximum URL length, but implementation varies by browser and version. For example, Internet Explorer does not support URLs that have more than 2083 characters.[6][7] There is no limit on the number of parameters in a URL; only the raw (as opposed to URL encoded) character length of the URL matters. Web servers may also impose limits on the length of the query string, depending on how the URL and query string is stored. If the URL is too long, the web server fails with the 414 Request-URI Too Long HTTP status code.
I would probably use a cookie to store the object.
I've got an index page which sends users to an edit products page on separate browser tabs.
For each products edited the index rewrites the Session["ProductID"].
The Edit page then has the following code to have a unique identifier for this tab and product:
if (!IsPostBack) //first time page load
{
Random R = new Random(DateTime.Now.Millisecond + DateTime.Now.Second * 1000 + DateTime.Now.Minute * 60000 + DateTime.Now.Minute * 3600000);
PageID.Value = R.Next().ToString();
Session[PageID.Value + "ProductID"] = Session["ProductID"];
}
This works, and when the same user opens multiple tabs I only reference the Session[PageID.Value + "ProductID"] in my code so that I always have the proper ID. (I'm working in a trusted environment this is for an intranet, therefore I'm not too bothered with the level of security).
My issue occurs if the user does a page refresh by hitting the F5 key. At which point the Session[PageID.Value + "ProductID"] gets the Session["ProductID"] of the last product he opened.
For example:
User 1 opens product1 in tab1
User 1 opens product2 in tab2
Whenever they use the tool normally, everything works fine. However if:
User 1 on product1 page hits the refresh button (F5) the product1 page becomes product2 page
Is there a way to detect a page refresh from a "first load/redirect from another page" so that I can then tell my page not to update my Session[PageID.Value + "ProductID"]?
Personally, I would go for URL parameters. E.g. pass the product IDs as URL parameters.
If you need the pages without parameters, you could e.g.
Pass parameter to page.
Page reloads itself if parameter is present and removes the parameter
This way you could distingues between first call (=parameter present) and second+ call (parameter not present).
I've solved a very similar issue by storing two versions of a state-identifying parameter: one in Session and one in either the ViewState or the URL (QueryString).
If you compare the two values on Page_Load, that will tell you whether the session variable has changed since the page was first loaded. This should be just what you need.
EDIT: Rough sketch of the code (warning - haven't seen the actual code since I wrote it 3 years ago):
protected string currentProductID
{
get
{
return Request.QueryString["ProductID"];
//or:
//return (string)ViewState["ProductID"];
//or:
//return HiddenField1.Value;
}
set
{
Response.Redirect(ResolveUrl("~/MyPage.aspx?ProductID=" + value));
//or:
//ViewState.Add("ProductID", value);
//or:
//HiddenField1.Value = value;
}
}
protected void Page_Load(object sender, EventArgs e)
{
//If the problem only occurs when not posting back, wrap the below in
// an if(!IsPostBack) block. My past issue occurred on both postbacks
// and page refreshes.
//Note: I'm assuming Session["ProductID"] should never be null.
if (currentProductID == null)
{
//Loading page for the first time.
currentProductID = (string)Session["ProductID"];
}
else if (currentProductID != Session["ProductID"])
{
//ProductID has changed since the page was first loaded, so react accordingly.
//You can use the original ProductID from the first load, or reset it to match the one in the Session.
//If you use the earlier one, you may or may not want to reset the one in Session to match.
}
}
In the above code, note that changes to the ViewState (including the value of a Hidden control) will only take effect on the next PostBack. On a refresh, they'll revert to their most recent value. In my case, that was what I wanted, but it sounds like it's not quite right for your situation. Still, that information could be useful to you, depending on how you implement this.
I've left out a discussion of comparing currentProductID to Session[PageID.Value + "ProductID"], since I've already posted a lot of code, and I don't know the details of what you're trying to do. But there are various ways you can use Session, ViewState, and the QueryString to glean information about the state and history of the page.
Hopefully that should give you the general idea. Let me know if that's not enough to get you going.
You may want to have a look at this. I think it's close to what you're looking for.