What triggers an System.InvalidCastException in ASP.NET? - asp.net

I have an issue on my ASP.NET 4.0 application. The error appears when I call one of my subroutines in the App_Code folder. I call the subroutine when a button is clicked on the page.
Protected Sub imgBtnEmailReg_Click(ByVal sender As Object, ByVal e As System.Web.UI.ImageClickEventArgs) Handles imgBtnEmailReg.Click
Dim functions As New Functions
Dim pidm As Integer = Convert.ToInt32(Session("BannerPidm").ToString)
functions.sendStudentAccomLetter(pidm)
End Sub
After the button click the id number is sent to the App_Code/Functions.vb where my subroutine is:
Public Sub sendStudentAccomLetter(ByVal stuPidm As Integer)
...
End Sub
The error I get when calling the above function is:
"System.InvalidCastException: Specified cast is not valid. at Functions.sendStudentAccomLetter(Int32 stuPidm) in D:\www-sec-docs\DisabilityServices\App_Code\Functions.vb:line 259"
Line 259 is the sub signature. I'm not even sure if there is a cast occurring here. Can someone please explain what might be causing this. Thank you.

Your Session("BannerPidm") value may be a different type - the method declaration is not the cause of the cast error. Try implementing some kind of check on the Session("BannerPidm") value such as:
If IsNumeric(Session("BannerPidm")) Then
'Proceed

This link shows a few examples where you would get and error when trying to convert: http://bytes.com/topic/visual-basic-net/answers/514682-difference-between-cint-convert-toint32
Try using CInt() instead and see if you still have problems. If you do, then you may want to start checking what the session variable is and see if there is a better, more standardized way you can store it.

It is most likely the conversion to Int32. Set a breakpoint at that line, and see what value Session("BannerPidm")
is returning. There is definitely a cast occurring, because you are retrieving from Session, casting it to string (.ToString()), then converting that to Int32.

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

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!

Try/Catch in Global.asax while logging errors to db needed?

So I handle all exceptions in my project within my Global.asax page. For example, on a random page I could have:
Protected Sub SomeFunction()
Try
'do something here
Catch ex As Exception
Throw ex
End Try
End Sub
So then the exception bubbles up to the Global.asax page where I handle it and log to the database like so:
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
Dim ex As Exception = Server.GetLastError
Dim loggedExceptionID As Integer = 0
Try
loggedExceptionID = New BLL.ExceptionHandler().LogException(ex)
Response.Redirect("~/ErrorPage.aspx?ID=" & loggedExceptionID, False)
Catch loggingError As Exception
'what do I do here?
End Try
End Sub
The BLL.ExceptionHandler().LogException(ex) function just writes the error details to the database.
So my question is in the Application_Error method, do I need the try/catch block when trying to write to the database? I'm thinking I would in case something goes wrong with the connection, etc. - but is this really necessary? Also, what would I do in the catch block if there is an error? At that point I would be catching the error of logging an error which is confusing in its own right.
It's probably a good idea to have a try/catch there, and what I would do is write the details to a text file or xml file so that you can refer back to both errors in the future and try to fix them. That of course means you would probably want another try/catch around writing to the disk, in which case I would just give up and call it a day. =)
On a completely separate note, you really should check out ELMAH: http://code.google.com/p/elmah/. This does probably everything you want and a lot more.

Error handling using events, checking if an error happened and react accordingly

I have an object, say Order where if an error occurs, it raises the ErrorOccurred event. If I'm running some code in say, the codebehind for a .aspx page with an public Order registered as WithEvents and I want to check to see if an error has occurred before I run more code, how do I do this? I can't simply check theOrder.ErrorOccurred. Do I have to create a local boolean flag that switches over in the event handler (OnErrorOccurred)? Or is there a better way to do this?
Thanks!
Example:
Public WithEvents theOrder As New Order
Public Sub DoStuff()
theOrder.DoSomething()
If theOrder.ErrorOccurred Then
do stuff
End If
End Sub
That seems like a reasonable approach. If there is lots of logic going on with an Order object that depends on knowing about errors, having a Status field would allow easy communication to any consumer what the status of the order was, rather than everyone having to subscribe to the event and track it themselves.
Alternately you could track it internally in the Order and just throw exceptions when critical methods were accessed if the Order was in an error state. This has the disadvantage of making you do more error handling, but would have the advantage of making sure that any Order consumer handled them explicitly.
Why not use structured error handling?
Try
'Code that may raise an error.
Catch
'Code to handle the error.
Finally
'Code to do any final clean up.
End Try
http://support.microsoft.com/kb/315965
This is what it is intended for.
Problems may arize if someone calls DoSomething but thay are unaware that they need to check theOrder.ErrorOccurred. based on what DoSomething is doing, allowing one to call a method and letting it fail quietly can be a problem.
If do something is doing logging sure, let it fail. If it is finalizing an order process..
Brian
Use the Try Catch Block
Try
'try your code here
Catch somevariablenamehere As Exception
'use methods from Exception class to get to know the error better and how to deal with it
Finally
'this is optional, If you want to do something finally, like cleaning up etc. You can do here
End Try
'to end the Try block

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