allowing only one instance of page - asp.net

i have a question about allowing only one pageinstance in all clientsessions. So if a client ask for the unique page and there is already a session with this page. The client which ask for the page should get a messagebox, which say "This page is already in use"
I read about this problem on forums. Many people say "it's impossible to get out if the client have close the browser (including the unique page)".
Is that true about the serverside?
Is there a way to handling this problem?
Is use Asp.net with Vb.net
i hope anyone understand me. My english is bad.

The problem with keeping track of whether the current user is still using the page can be managed by having an UpdatePanel with a Timer which then sets an application variable time every 500ms (or whatever interval you want)
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs)
Application["PageLastUsed"] = DateTime.Now;
End Sub
and redirect users if the page is in use
TimeSpan duration = DateTime.Now - (DateTime)Application["PageLastUsed"];
if (duration.TotalSeconds < 2)
{
Response.Redirect("InUsePage.aspx");
}
See timer info here http://msdn.microsoft.com/en-us/library/cc295400.aspx

Related

Send Email without waiting for the action to finish execution after Button click ASP.NET

In short, remaining in the HTTP context, I would like the user, after clicking on an order completion button, not to wait for the mails to be sent before being sent back to a "thak you page".
I saw that HostingEnvironment.QueueBackgroundWorkItem could help me with this but there is always the risk of it being killed by IIS recycling.
What is the best solution to do this?
I know the best would be to develop a separate console solution but it wouldn't be worth it for 3/4 emails, alternatively I could consider speeding it up by making them asynchronous?
Protected Sub btnConcludiOrdine_Click(sender As Object, e As System.EventArgs) Handles btnConcludiOrdine.Click
If IsValidOrder(Me._cart, msg) Then
If Me._cart.SaveOrder(Me._user, Me._orderCode, Me._lang) then
'Update quantity in db
Dim mail As New EmailBLL
mail.SendOrderNotice(Me._cart, Me._lang) '2 Mails
mail.SendProductNotice() '2 Mails
End If
Else
Response.Redirect("*Error URL*")
End If
End Sub
The way you approach this is as suggested – start a task, or so called new processor thread.
So, what you would do is break out the code – this even works if code behind is for a web form.
So, the first step is to move out the “slow” parts, or the parts we want to run separate.
The main issue is that to start/launch/want/desire/achieve a brand new processor thread?
The sub call CAN ONLY PASS ONE “parameter” and the sub can only accept one parameter!!!!!
I note in your case that routine needs two values.
However, that “one parameter” can be a array of “many” values, or even a collection or whatever. In our case we pass the two values.
So just keep in mind that what you call can NOT update or “use” the values of controls on the form – the instance of that form will go out of scope.
But we can of course PASS the values you need. This will allow that routine to run 100% independent of the web form.
I also VERY strong suggest that if you DO place the sub in the same web page code behind? You should/can mark that sub as shared. Doing so will allow the compiler to get mad at you and spit out errors if that routine say tries to use or update a control value on the form.
However, it is MUCH better is to place this sub in a separate standard code module out side of the web forms code behind.
Regardless of above, we can now re-write the code we have as this:
If Me._cart.SaveOrder(Me._user, Me._orderCode, Me._lang) then
Dim myInfo(1) as object
myInfo(0) = me.cart
myInfo(1) = me_._lng
Call MyUpdateQ(myInfo)
End If
' bla bla lba
Shared Sub MyUPdateQ(p() as object)
'Update quantity in db
Dim mail As New EmailBLL
mail.SendOrderNotice(p(0),p(1)
mail.SendProductNotice() '2 Mails
End Sub
Ok, so far, we not achieved much, but we re-writing to accept the ONE array is KEY here.
So, now now make sure the above runs/works and is all happy.
Now, because we moved out the "work load" to that one routine, it is now a simple matter to start a thread.
Now, Our above code becomes this:
Protected Sub btnConcludiOrdine_Click(sender As Object, e As System.EventArgs) Handles btnConcludiOrdine.Click
If IsValidOrder(Me._cart, msg) Then
If Me._cart.SaveOrder(Me._user, Me._orderCode, Me._lang) then
Dim myInfo(1) as object
myInfo(0) = me.cart
myInfo(1) = me_._lng
Dim MyThread As New Thread(New ParameterizedThreadStart(AddressOf MyUpdateQ))
MyThread.Start(myInfo)
End If
Else
Response.Redirect("*Error URL*")
End If
End Sub
Shared Sub MyUPdateQ(p() as object)
'Update quantity in db
Dim mail As New EmailBLL
mail.SendOrderNotice(p(0),p(1)
mail.SendProductNotice() '2 Mails
End Sub
That is it. Now when you click your button it will wait ZERO time, since the long running routine is now going to run 100% as a separate thread. And this will also mean that when the user clicks the button - the page will respond instant and post back to user will be done. So if that thread takes 6 seconds, or even 25 seconds, the user will not notice this delay.
Just push your sending mail logic in Task and if you are not interested in result don't await it. c# syntax
Task.Run(() => SendEmail());

Using a timer to move between Views in a MultiView control

I'm trying to get a timer to move between 3 Views in a MultiView control here is the code I'm using:
Protected Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim activeView As String
activeView = MultiView1.GetActiveView().ID
If activeView = "View1" Then
MultiView1.SetActiveView(View2)
End If
If activeView = "View2" Then
MultiView1.SetActiveView(View3)
End If
If activeView = "View3" Then
MultiView1.SetActiveView(View1)
End If
End Sub
On page load I have the MultiView Control set to View1 (MultiView1.SetActiveView(View1))
The page loads correctly and the data (being pulled from an SQL server is visible. After the first tick on timer1 the second view appears again showing the correct data. Then nothing I can see the reload button on the browser going at the timer interval but I never see View3 or a return to View1
Before anyone suggests I had build the If statement as If, ElseIf, EndIf but I broke it out into separate If statements to see if that would help.
It didn't.
I Hope someone can help
Cheers
Have you tried to debug your code with breaks, try to put a break in the If...End If blocks and watch if it is reachable.
You may be having different IDs set for your views, or maybe some cASE mismatching. I will suggest, rather comparing view's ID string, it is safe to compare views index by MultiView1.ActiveViewIndex, this will return only an integer which is lot safer to compare.
Hope it will work.
Sometimes I wonder if I should be let out without a carer.
I found out why the views or label.text changes weren't progressing. I had set the startup info in page_load so even though the timer was firing it was doing a page_load which was defaulting back to the original data.
Sorry for the waste of your time.
I'm off to slowly bang my head against the wall until it doesn't hurt anymore then return to my project.

Can you trust ViewState to handle program control?

I've read a lot about ViewState on MSDN and looked at these questions (among others):
Can malicious users modify viewstate?
How to modify viewstate of a label in ASP.net
I see that if you have EnableViewStateMac turned on, ViewState is signed with a calculated value called a MAC to detect if it's been tampered with during round-trips, and ASP.NET will throw an exception if it detects that the MAC does not match the client's ViewState data.
To me, this means that it is safe unless the private key used to sign the ViewState is somehow reverse-engineered, similar to how SSL cryptography works. Hopefully this is true, but correct me if it's not. I might be missing another piece to how ASP.NET works internally, but it seems to me that you should be able to rely on a control's state to control program execution and flow, since the only way to modify the control's state is in server code based on a postback containing valid changes to the client's form.
The question is: Practically, is it okay to use a control's state (if it is not supposed to be changeable by the user) for programmatic decisions, and what are the possible dangers and how could those cause a practical problem?
Here are two specific examples of what I'm wondering is safe from bypassing via ViewState tampering (this is a mock-up of what I'm doing):
Example 1
Public Sub SetPageState()
If User.IsLoggedIn() Then
MultiView1.ActiveViewIndex = 0 'user is logged in
Else
MultiView1.ActiveViewIndex = 1 'user is not logged in
End If
End Sub
Private Sub PersonalizePage()
If MultiView1.ActiveViewIndex = 0 Then
'Do logged-in stuff
ElseIf MultiView1.ActiveViewIndex = 1
'Do not-logged-in stuff
End If
End Sub
Example 2
Public Sub SetUserLoginControl()
Label1.Visible = User.IsLoggedIn()
End Sub
Private Sub DoLoginThings()
If Label1.Visible Then
'Do logged-in stuff
Else
'Do not-logged-in stuff
End If
End Sub
I realize the "correct" way would be to check for User.IsLoggedIn() (or whatever needs checked) in every place where that's what is supposed to be controlling it, but in some cases the function is computationally expensive, and it's much cheaper to check the state of a control that was modified based on the return value of the expensive function. I realize there are ways around this, such as storing a temporary copy of the function return value, etc., but this is more of a conceptual question than a "here's my problem, now solve it for me" question.
Your code when using controls is unreadable which is bad. You might want to cache state of User.IsLoggedIn() in HttpContect.Current.Items dictionary. It's somewhat a cache that lives for a single request only.

Calling a method on Session Timeout?

I have a website with multiple pages. Each page has a "Save as Draft" method that will save the users progress. I have a session timeout of 40 minutes, and I was wondering how I would make it so that whenever the session is expired, the page automatically calls "Save as Draft" (so it's not lost)
How would I start on doing something like this?
You can't: the session expires server side and cannot send a message to the browser (it doesn't even know whether the user still sees the page or has closed the browser).
You could set a client-side timeout to save the page (as draft) to the server, but this has the effect of refreshing the session! So maybe just do an automatic "save as draft" every 5 - 10 minutes, thereby keeping your session (plus a draft copy of the work done).
In .Net, you can do it via Global.asax in Session_End(object sender, EventArgs e) routine. I use this to do some resource release work.
you can call function in global.asax when session expire's like this
Sub Session_End(ByVal sender As Object, ByVal e As EventArgs)
If Not Session.Item("sessionid") Is Nothing Then
If Session.Item("sessionid").ToString = "1" Then
ClsUtilities.CustomerLogout()
ElseIf Session.Item("sessionid").ToString = "2" Then
ClsUtilities.Logout()
End If
End If
End Sub

Calendar Selection

Greetings,
Might be having a brain fart this morning, but I need a way to execute some JavaScript at the conclusion of an operation taking place inside an ASP .NET Ajax Update Panel. How can this be accomplished?
Thanks,
jason
Updated based on responses:
I was not entirely clear, as both initial answers were correct given what I was asking. In my case I ONLY want the JS to run when a particular event for the control inside the UpdatePanel is executed, sorry for the confusion.
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequest);
function endRequest(sender, args) {
// Executed when ajax request finishes, you could check the sender variable
// in order to identify which update panel fired the request
}
Here's a good article on it. I think this is exactly what you're looking for:
http://blog.jeromeparadis.com/archive/2007/03/01/1501.aspx
Only caveat is that this sample works against any ajax callback so if you have multiple updatepanels it will fire regardless of which one has completed a roundtrip, etc.
Thanks to KevinP and Darin for their answers. I had actually forgotton about the instance request handlers on script manager. Unfortunetly, in my case I would be firing the end_request everytime the person navigated in the calendar control. I take the blame as I was not clear on all requirements. I have upvoted both of their answers. Here is my final solutions.
(Forgive me this is in VB)
Protected Sub mainCalendar_SelectionChanged(ByVal sender As Object, ByVal ev As EventArgs)
Dim dtStart As DateTime = mainCalendar.SelectedDates(0)
Dim dtEnd As DateTime = mainCalendar.SelectedDates(6)
Dim alertString As String = _
String.Format(
"alert('{0}');", dtStart.ToString("d") + " - " + dtEnd.ToString("d")
)
scriptManager.RegisterStartupScript(upCalendar, GetType(String), _
"alert", alertString, True)
End Sub
In this context the alert is only ever displayed on the selection of a week in the calendar, not when the user changes the month or does something else relating to navigation.
Thanks again to both responders for their help

Resources