Using a timer to move between Views in a MultiView control - asp.net

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.

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());

multiple upload, ajax control

im trying to upload multiple file and save all the files in a data table.
the data table is storing only one file.
Help me to solve, im having error in the else part. dtupload is highlighted
Below is what I have tried:
Private Sub AjaxFileUpload1_UploadComplete(sender As Object, e As AjaxControlToolkit.AjaxFileUploadEventArgs) Handles AjaxFileUpload1.UploadComplete
Try
dt.Rows.Add(UploadDocPath, UploadDoc)
MsgBox(dt.Rows.Count.ToString)
Else
dt.Rows.Add(UploadDocPath, UploadDoc)
End If
Catch ex As Exception
End Try
End Sub
Well, you in ONE local routine create a table, add a row. And then the routine finishes and all the values, variables now go out of scope. Then that routine will be called again if a 2nd file is up-loaded, and you re-create the table. The variables in that routine (and in fact ANY routine - heck even if this was not asp.net go out of scope when the routine finishes.
At least with a desktop application you could declare the table at the form level (not sub routine level) and then you could add a new row to that temp table variable. But, with asp.net, then your web page is "state less". That means all variables ONLY have their state when code runs. The instant that code is finished, then all state in the code behind is lost.
But I am somewhat perplexed that you would think the data table would persist for each call? Perhaps you only want the var dtUpload to exist in the lifetime of each separate time that routine is called? But, then again you do nothing with the table????
So, for each file up-loaded? That routine gets called.
So, lets assume 5 files are to be up-loaded.
Taking a really wild guess? I would assume we want that table/array to build up over time.
So, we need to ensure that the dtUpload table can "live" beyond a single page cycle and round trip.
So, lets save/place/put/park the dtUpload table that can live "beyond" that one routine.
It really depends on what you want to do with that list after all is said and done?
Since the table is small? Then you could certainly in the forms on-load event create that table with no rows and shove it into say the Session(). Then as each file up-loads you could shove the file name into that array.
So, your code could work like this:
In on-load event only FIRST time, create the dtUpload table. And then shove/save it into the session().
So, our on-load would look like this:
If IsPostBack = False Then
' fist time page load - create our table
Dim dtUpload As New DataTable
dtUpload.Columns.Add("PATH")
dtUpload.Columns.Add("FILENAME")
Session("FileList") = dtUpload
End If
Ok, so when the page loads (first time only), we create the dtTable and THEN save it in the session.
Now, in the file upload done event, grab the table from session, add the row (file + path).
And note HOW we don't have to shove the dtUpload table BACK into the session! (it is now a persisting object in our session).
Ok, so now our single file load event (when done) can/will look like this:
Protected Sub AjaxFileUpload1_UploadComplete(sender As Object,
e As AjaxControlToolkit.AjaxFileUploadEventArgs) Handles AjaxFileUpload1.UploadComplete
Dim dtUpload As DataTable = Session("FileList")
Dim strPath As String = "c:\Test\MyUpload\"
Dim strFile As String = e.FileName
dtUpload.Rows.Add(strPath, strFile)
AjaxFileUpload1.SaveAs(strPath & strFile)
End Sub
So, note how we add the one row to the table. (and we don't as noted have to shove the object back into the session - dtUpload in this case is in effect a object pointing to persisting dtUpload table we placed into Session().
Ok, so, now lets say all 5 files are done.
Well, you now have to decide what you want to do with the dtUpload table you have?
Perhaps we want to display all the files?
Well, keep in mind that the web page does not do a post back.
But, lets assume we now want to display all files.
Drag onto the form a datagrid control.
Drag onto the form a button.
So, we now have this:
Then hit up-load, you get this:
When you click on the the button, you can run this code:
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Me.GridView1.DataSource = Session("FileList")
Me.DataBind()
End Sub
And now click on that button?
And you see this:
Now here is a really huge, large, massive, VERY important reason why placed that button on the form. The reason of course is when the ajax upload is all done?
The web page does NOT do a post back. So, that is where the button above comes into play.
By clicking the button, then our code stub runs, we fill the gridview, and then of course the page makes the round trip and re-displays our file list.
Now, we could have the final CLient side ajaxfileupload event click on that button for us, and thus in place of the user clicking that button to continue?
You can have client side code click on that button for you.
So, set the OnClientUpLoadCompleteAll to the js routine:
<script>
function uerror() {
alert('upload error');
}
function myalldone() {
var btn = document.getElementById('<%=Button1.ClientID%>');
btn.click();
}
</script>
So it will now click that button (you could even set style="display:none" for the button. So, now you have a final routine server side, but with a full page post back.

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.

Executing a VB WebMethod from javascript

I'm trying to eliminate a VB.NET button on my aspx page. Trying to use javascript and ajax to execute the same code my vb had.
I put in a script manager, set EnablePageMethods to true, added a static subroutine, and referred to it in my javascript function (BTW -- this seems a lot of work just to execute an existing subroutine). The javascript calls my code-behind and it almost works.
Problem is, now I'm getting a NullReferenceException when SimulatePrintBatchClick tries to do anything with the controls.
Error is 'Object reference not set to an instance of an object', line is 'pnlVars.Controls.Clear'
Here's the code from UW.aspx:
<WebMethod()> _
Public Shared Sub PrintBatchFromJSWM()
Dim UWI As New UW
UWI.SimulatePrintBatchClick()
End Sub
Sub SimulatePrintBatchClick()
Dim Client As New LetterWriterClient
'Run ExStream and get the PDF File
Globals.PDF_Data = Nothing
Globals.PDF_Data = Client.ProcessDatFile(Session("SessionID").ToString)
'Reload the form -- turn off all controls, initialize variables and make the PDF iFrame visible
pnlVars.Controls.Clear() 'Bombs out on THIS line of code
pnlPDF.Visible = True
Me.SendToBach.Visible = False
Session.Contents("LetterVariables") = Nothing
Session.Contents("PolicyInformation") = Nothing
Session.Contents("Submitted") = True
Response.Redirect("UW.aspx")
End Sub
Funny, when I run the above code in PrintBatch_Click it all executes just fine. I really don't understand why it bombs out as a subroutine.
Perhaps this is not the way to do this, but I'm at a loss for finding a different way. Originally this code was handled by an ASP/VB button, but the specs have called for it to be deleted.
Any way I can get the above code to do it's job?
Thanks,
Jason
You cannot use any server controls in WebMethod or AjaxMethod as they are not part of Page life cycle, access these controls in Javascript.

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