Executing a VB WebMethod from javascript - asp.net

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.

Related

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.

if then logic failing to execute code block

I have the following code logic in my vb.net(.net 4.7) page that is supposed to check the value of a session object.
If that object is not nothing and that object does not equal a specific string, then the code block between the if and end if statements is supposed to be executed.
But no matter what I do, it never gets executed.
I even tried setting a breakpoint in Visual Studio to see what the value of Session("buildingID") is, and even if it's something like this:
Session("buildingID") = "991c"
The code block is never hit.
Here is the logic:
If Session("buildingID") IsNot Nothing AndAlso Not Session("buildingID").ToString = "543a" Then
'Do Stuff
End If
The Session object is of type
System.Web.SessionState.HttpSessionState
What could be causing this?
Thanks!

CEFSharp bound object lost when new website is loaded

I am using CEFSharp in one of my projects and all works perfectly fine so far.
I am still on V63 of CEFSharp (never touch a running system :-) )
I am using it in VB.NET
The bound object is created after CEFSharp initialisation within Public Sub New() as follows:
CefSharpSettings.LegacyJavascriptBindingEnabled = True
Dim obj As New BoundObject()
obj.browser = browser
browser.RegisterJsObject("bound", obj)
AddHandler browser.LoadingStateChanged, AddressOf obj.Browser_LoadingStateChanged
I am then after each "LoadingStateChanged" event of the browser execute a JS script with browser.ExecuteScriptAsync.....its basically an event listner that will fire the bound object when the event occurs (e.g. a mousclick).
This also so far works 100% OK....the event fires and calls the bound object and passes a variable to my VB.NET code via the bound object.
Now my problem is that after I load a new page the bound object is lost.
The event listner will try to call the bound object but I just get an error like "Uncaught ReferenceError: bound is not defined"
Looks like be loading a new page inside CEFSharp the bound object is lost.
I triead the above initialisation code also with FrameLoadEnd event instead, but it behaves exactly the same as LoadingStateChanged event.
Any clue anyone how I can handle (or renew) the bound object whenever I load a new website?
Thanks
Update:
In the meantime I tried the binding method V2 as recommended.
Using the following code for testing purpose:
'########### TEST CODE TEST CODE TEST CODE ##################
'try to use new binding V2 method by calling CefSharp.BindObjectAsync:
browser.ExecuteScriptAsync("CefSharp.BindObjectAsync(""myObject"");")
'now register object:
browser.JavascriptObjectRepository.Register("myObject", New BoundObject(), True)
'now do test execution of myObject:
browser.ExecuteScriptAsync("myObject(""test"");")
But still struggeling to get it working :-(
The last sugestion of amaitland solved the problem. it works now nicely across various sites. In principle I just replaced this two lines in my original working code:
Dim obj As New BoundObject()
obj.browser = browser
'browser.RegisterJsObject("bound", obj) 'replaced by next line (JS binding V2)
browser.JavascriptObjectRepository.Register("bound", obj, True, Nothing)
AddHandler browser.LoadingStateChanged, AddressOf obj.Browser_LoadingStateChanged
And then later within the Sub that handles the browser_LoadingStateChangedAsync event I just added this line beofre any other injected JS:
'use new binding V2 method by calling CefSharp.BindObjectAsync:
browser.ExecuteScriptAsync("CefSharp.BindObjectAsync(""bound"");")
I hope this helps others using CEFsharpin VB.NET if they come across the same problem.
For anyone trying to do the same thing in C# (like me):
Browser.JavascriptObjectRepository.Register("myObject", interf, true);
Browser.LoadingStateChanged += (s, a) =>
{
if (a.IsLoading) return;
Browser.ExecuteScriptAsync("CefSharp.BindObjectAsync(\"myObject\");");
};
I've added checking the IsLoading state, as there is no reason to bind the object when the browser starts loading (at least in my use case).

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.

InsertOnSubmit not triggering a database insert on SubmitChanges

I'm experiencing an odd scenario and I'm looking for ways to figure out what's going wrong. I've got a piece of code that inserts a row into a table - the kind of thing I've done in dozens of other apps - but the end result is nothing happens on the database end, and no errors are generated. How do I find out what's going wrong?
Here's my code:
Partial Class MyDatabaseDataContext
Public Sub CreateEnrollee(subId, depId)
dim newEnrollee = New enrolee With {.subId = subId, .depId = depId}
Me.enrollees.InsertOnSubmit(newEnrollee)
Me.SubmitChanges()
dim test = NewEnrollee.id '<-- auto-incrementing key'
End Sub
End Class
After SubmitChanges is called, no new row is created, and "test" is zero. No errors are generated. I have no idea why it's not trying to insert the row. Any ideas on how to debug this?
You could enable logging:
Me.Log = Console.Out;
You could check the ChangeSet for your object.
FOUND IT! Part of the debugging I did for some other issues included adding some logging to some of the extensibility methods:
Partial Private Sub InsertEnrollee(instance As Enrollee)
End Sub
I thought "InsertEnrollee" existed so I could perform actions after the Enrollee was inserted, so I added logging code here and that's when the trouble started. Now I'm guessing this is how you would override the Enrollee insert and do it yourself if you so desired. Since I was essentially overriding with logging code, that's why nothing was happening (from a database perspective).

Resources