ASP.NET Details View - Editing into Null Value Error - asp.net

I am using ASP.NET in Visual Studio 2010.
I have a website that features a shopping cart, the user can signup which has validation using the RequiredFieldValidator control meaning they must enter something for certain fields e.g. Address 1 / E-Mail. This is also tied to a Database which for these fields does not allow null values.
My issue that is after logging in, adding items to cart, quantities etc, I have a confirmation order page - similar to most online shopping websites were the shopping basket is displayed along with the user's Customer Details, which is shown through a DetailsView, connected to a SqlDataSource which is running a query that just displays their shipping details as previously entered.
However, if I say select Edit, which is using the DetailsView's own property and change the Address1 line to nothing, the DetailsView sends it as null value after accepting and as a result the whole thing crashes.
I have tried examples like:
Protected Sub DetailsView1_PageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DetailsViewPageEventArgs) Handles DetailsView1.PageIndexChanging
Try
Catch ex As Exception
lblError.Text = "Please verify changes made to Customer Details."
End Try
End Sub
Protected Sub DetailsView1_ItemUpdating(ByVal sender As Object, ByVal e As DetailsViewUpdateEventArgs) Handles DetailsView1.ItemUpdating
Try
Catch ex As Exception
lblError.Text = "Please verify changes made to Customer Details."
End Try
End Sub
Protected Sub detailsView1_ItemUpdated(ByVal sender As Object, ByVal e As DetailsViewUpdateEventArgs) Handles DetailsView1.ItemUpdating
Try
Catch ex As Exception
lblError.Text = "Please verify changes made to Customer Details."
End Try
End Sub
So basically Try / Catch statements which has worked for everything else. But because I can't get access to any proper code behind for the DetailsView since it's just taken from Visual Studio I'm stumped. Has left me curious now, looked about here and elsewhere and couldn't find much, anything seemed similar to what I've tried there but they don't make a difference.
I want to try and create/find some form of Error Handling for this situation, similar to registering, either not proceeding with sending to the server if left blank or display a message.
This is the main part of the error:
[SqlException (0x80131904): Cannot insert the value NULL into column 'Address1', table 'C:\USERS\xxxx\PROJ (2)\PROJ\APP_DATA\ORDERS.MDF.dbo.Customer'; column does not allow nulls. UPDATE fails.
The statement has been terminated.]
Something simple I'm missing? Was considering the option of creating text boxes instead and connecting to the database individually, but that's a completely different route to this and there is quite nice, simple customizable options with the DetailsView.

Well...typical after spending weeks confused by this one I managed to get it just after posting the question.
For anyone interested in this I used the 'If e.Exception Is Nothing Then' statement within the code similar to the two bottom examples I tried, THEN, used a Try/Catch statement.

Related

How to store User ID of Logged in User in ASP.net VB.net

I am trying to store the UserId or/and UserName of the user. This is used to record user ID against any changes they make to data, insert, updates and deletes etc.
I have created a module and in that module added a Public variable vUserID. Here Lei the problem.
User A logs in and his id vUserID = 'A'. Another user (User B), the other side of the world logs in User 'B' and that vUserID then = 'B'. So now anything User A does gets recorded as he is User 'B', or that is how I understand it, as a Public variable will be accessible from anyone who logs in.
I understand the problem, or I think I do, please correct me if not, but what I am struggling with is the solution. I have tried to use a Protected and Protected Friend but these do not seem to be accessible throughout the program(website) when a user is logged in.
For completeness I get the User details by the following code which seems to work fine:
Dim mu As System.Web.Security.MembershipUser = System.Web.Security.Membership.GetUser()
Module1.vUserID = mu.ProviderUserKey.ToString()
Well, the issue is that you have ONE web server.
And the web server (for the most part) will process ONE web page at a time.
So, when a user clicks a button on a web page, before they click on a button, the web page is sitting on their desktop computer. it is NOT on the web server.
(and more important, all the code variables (code behind) are GONE! They do not exist yet!).
So, think of a web server as ONE computer. And say 5 users are going to use YOUR computer to edit a word document.
The first user sits down, opens word document, types in some text, and then closes word!
The next user sits down, opens word document, types in some text, and then closes word!
Remember, you don't have a computer for each user, but have ONE computer - the web server, and it has to "some how" service all users.
So, all the web server can do, is "process" a web page, one that is sitting on each end users computer (running the browser).
So, you have this:
And you do NOT have this:
In other words, the web page is NOT sitting "loaded" on the web server. it is out of scope.
Think of when you call a sub, use some variables in that sub, when you return/exit from that sub, ALL VARIABLES are gone!! (out of scope).
You MUST think of web pages like that sub - when you exit, they are gone, don't exist anymore.
So, you don't have this:
the web page is NOT in memory on the server, it is NOT loaded.
Thus, you don't have this either:
So, with above in mind, lets create a super simple web page to show this:
We will have a simple string variable, called MyZooVar.
We will put a button and label on the web page to set this varible.
we will then put another button on the form to show the value of the variable.
So, this:
<asp:Button ID="cmdSetZoo" runat="server" Text="set varable to zoo" />
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
<br />
<br />
<asp:Button ID="cmdGetZoo" runat="server" Text="get value of var zoo" />
<asp:Label ID="Label2" runat="server" Text="Label"></asp:Label>
and the code behind is this:
Public MyZooVar As String
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Protected Sub cmdSetZoo_Click(sender As Object, e As EventArgs) Handles cmdSetZoo.Click
' set value to variable MyZoovar
MyZooVar = "Hello how are you!"
Label1.Text = "Value of MyZooVar = " & MyZooVar
End Sub
Protected Sub cmdGetZoo_Click(sender As Object, e As EventArgs) Handles cmdGetZoo.Click
' get/show value of zoo var
Label2.Text = "Value of MyZoovar = " & MyZooVar
End Sub
Note VERY close in above, the MyZooVar - we defined it at the top of module, so all buttons and code can use that MyZooVar.
So, we will click the first button, this code:
' set value to variable MyZoovar
MyZooVar = "Hello how are you!"
Label1.Text = "Value of MyZooVar = " & MyZooVar
And then we have a 2nd button, and this code:
Protected Sub cmdGetZoo_Click(sender As Object, e As EventArgs) Handles cmdGetZoo.Click
' get/show value of zoo var
Label2.Text = "Value of MyZoovar = " & MyZooVar
End Sub
what will happen when we run?
We see this:
So, in above, this is what occured:
we START with this:
You click a button, YOUR web page (not the 20 other users) is sent to the web server.
the page travels up to server,
You now have this:
Now and THEN your code behind runs. When done, your code behind MUST finish, else the page stays stuck up on the server side. When done, the whole page page makes the trip down back to the browser. And THEN the page is re-displayed and THEN any js code can run.
So when done? Your page makes the trip back down to the browser like this:
Note on the server side? Your web code (and MORE important variables) and EVERYTHING is disposed.
We now have this again:
Note HOW THE WEB PAGE IS NOT on the web server!!!!
the web server is waiting now for ANY post-back of a web page from ANY user, not just you the one user!!!!
So, now that I clicked the button to set the variable MyZooVar?
What happens if I click on the 2nd button, this code:
Protected Sub cmdGetZoo_Click(sender As Object, e As EventArgs) Handles cmdGetZoo.Click
' get/show value of zoo var
Label2.Text = "Value of MyZoovar = " & MyZooVar
End Sub
Well, the whole process starts over again!!!
We will find that the variable MyZooVar is gone, out of scope, and does not have our value!!!
So, the "term" for the above is what we call "state-less".
In other words, your code behind can't assume, hope, pray that the varibles in the web page will persit.
Now you can hope/pray/try to put some variables in a global code module, but as you found out, they are shared amoung all users. But WORSE, the web server will often say, hey, I don't need that memory, I'm just sitting here waiting for someone to click a button and send me THEIR web page.
As a result, not only will you find those so called global variables in that public code module shared between all users, you find that they OFTEN will not even stay in memory all that long. So, your code "sort of works" to try and use some global variables, but you find they OFTEN go out of scope, and will not even stay in memory.
So, web based software is VERY different then desktop software.
One big difference is that for desktop software, each user, each workstation has their OWN copy of the code.
With a web server, you have ONE web server, ONE computer, and it sole job is to process incoming web pages (that occurs due to a page post-back).
the process of a simple button click, whole web page travel up to web server, page is processed, and then whole page is send back to user? We call this a round trip.
So, you really do not have global variables in a web based application. You can try to use some, but as noted, they will be the same for all users, but MUCH worse, is they tend to go out of scope, and can be disposed (go away) at any old time - you have no control over this, and thus you simple can't adopt global variables in a web based system - they are "off limits", and the above so called round tripping, and that you have ONE computer and ONE web site that somehow has to service many users - not just you!!
So, in your case?
Why do you need to store/save the user ID in some variable?
You "already" are able to get the user id with the code you shared:
You can use this:
dim UserID as integer
UserID = Membership.GetUser().ProviderUserKey
So, since you can get the "user" id any old time with above ProviderUserKey, then no need exists to try and "save" the user id into some global variable, but as you found out, you can't rely, or even design your software based around a concept of global variables.
However, you can if you wish place values into what we call "session".
Session is in effect global to the ONE user, and it DOES persist between those so called round trips.
so, you could do this:
Session("MyUserID") = Membership.GetUser().ProviderUserKey
And then in code, any time, use
Session("MyUserID") to get the user "id"
But, since you have ProviderUserKey, then even session() should not be required here.

Label is not visible . I need to show a message please wait when the user clicks login

Label is not visible in the following code . I need to show a message please wait when the user clicks login.It shows before but after adding the time interval its not showing
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Label3.Visible = True
If TextBox1.Text = "Akilan" And TextBox2.Text = "123" Then
System.Threading.Thread.Sleep(5000)
Form2.Show()
Hide()
Else
MsgBox("Sorry, The Username or Password was incorrect.", MsgBoxStyle.Critical, "Information")
End If
End Sub
Thread.Sleep on the UI thread will cause your form to "freeze". It sounds like you want some sort of waiting indicator while the background code is running.
What you should do is execute your long running code asynchronously, show your label, wait for the asynchronous code to finish, then do something (e.g. hide the label).
Using your code, it'd look something like this:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Label3.Show()
If (TextBox1.Text = "Akilan" AndAlso TextBox2.Text = "123") Then
Dim t = Task.Run(Sub() Threading.Thread.Sleep(5000))
t.Wait()
Label3.Hide()
Else
MessageBox.Show("Sorry, the username or password was incorrect", "Invalid Credentials", MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
End Sub
The way to do this is to hide/show the label text client side. Then when the page travels up to server and your code behind runs, the client side will still show that message. When you code behind is done, then the whole page now travels back down to the client side is re-load + re-display.
Grasping the above so called "round trip" is REALLY important here.
Since your code behind never interacts with the user, but only that copy of the web page that JUST traveled up to the server, and the code behind can play with, change and modif that page - but client side can ONLY see such updates AFTER the page travels all the way back down to client side. That's why this code can't work:
Label3.Visible = True
If TextBox1.Text = "Akilan" And TextBox2.Text = "123" Then
System.Threading.Thread.Sleep(5000)
Form2.Show()
Hide()
The above code will set Label.visible = true, but the whole page has not yet done its code, and the whole page is still on the server side. ONLY AFTER all your code is done, does the page travel back to client side, and show the label - but ALL code has to complete before page travels back down to client side.
However, this code will work just fine:
So lets look at above:
First up, we do NOT use visible=false for the label. The reason is that if you do that, then the label is NOT rendering in the markup.
Next up, we added a onclient click event to the button.
And we have our button code that has this code:
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Thread.Sleep(3000)
End Sub
So, when you run this, you see this for 3 seconds:
So what happens?
Well, you click on button - the OnClient code (javascrt client side) will run and THEN the post back of the page up to the server occurs.
So, since that label is now "show", then it will display. Now the web page is up on the server - your code behind runs. When code behind is done?
The WHOLE page now makes the trip back to browser client side. And this ALSO means our label message will automatic hide again - since the page is re-plotted with the whole new page that the server just send back to the client side.
Do note, that in above, I assumed jQuery is installed. If not then your script will have to be this:
function ShowLabel()
{
lbl = document.getElementById("lblMessage")
lbl.style.display = "inline"
}
Note also close how I set the id mode of lable = static - I often do that, since then referencing controls in js becomes a lot easier.
So, the real trick here?
We display the label client side, and then whatever and how ever long the server takes is the amount of time the label will display. And when that whole new fresh web page comes back down from the server, then the label will re-vert back to being hidden (display:none).
So, do keep in mind this VERY important concept of round trip. When you code runs behind and changes values or controls on the page? The end user does NOT see such changes until ALL code behind is done, AND THEN the page travels back down to the user. In fact, then your code behind to hide or show, can become before or after the delay in code - it will NOT update client side and in fact the order that that change label and delay will NOT matter (since the web page is STILL up on the server). So all your changes you make to the page remain up on the server until all code is done, and THEN the whole page comes back to client side to show such changes.
The other way would be to consider ajax calls - but baby steps here first, right?
You can make Button Click event asynchronous.
The following code works for me:
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Label3.Visible = True
If TextBox1.Text = "Akilan" And TextBox2.Text = "123" Then
Label3.Text = "Please wait"
Await Task.Delay(500)
Label3.Text = ""
Form2.Show()
Hide()
Else
MsgBox("Sorry, The Username or Password was incorrect.", MsgBoxStyle.Critical, "Information")
End If
End Sub
Also check:
Async (Visual Basic)
When to use Task.Delay, when to use Thread.Sleep?

ASP Email Validator

I have a textbox with multiple lines in it, each being an email address. I have a button that when clicked should read the emails from the textbox and validate that they are working emails (no spelling errors or anything). How would I go about doing something like this? For context the textbox is called emailBox
VB:
Protected Sub SaveButton(sender As Object, e As EventArgs)
End Sub
Thank you all so much in advanced!
Hi there I'm guessing by spelling errors you just mean valid email syntax.
You could use a regular expression. Like this:
Protected Sub SaveButton(sender As Object, e As EventArgs)
dim regexExpression As New Regex("^[_a-z0-9-]+(.[a-z0-9-]+)#[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z]{2,4})$")
'get an array of emails
dim emails = emailBox.text.Split(",")
'loop through emails checking each one
For Each email in emails
dim valid = regexExpression.IsMatch(email)
'do whatever with result
Next
End Sub
you will need to import this too, add it to the top of your file:
Imports System.Text.RegularExpressions
then the variable 'valid' will have a value of True or False that you can do what you like with.
I have edited my answer, assuming you can use a comma to separate your emails.
Edit 2: I can't guarantee the regex will work 100% correctly. Run your own tests, tweak it if need be or find/write another.

I need a line of code that updates text on a web page as per the day of the week

I need a line of code that updates to todays date on a web page.
It has to sit inside an asp website.
Any help appreciated.
Well based on the question and based on the details you've given us, the best thing I can suggest is this.
lblDate.Text = DateTime.Now.ToShortDateString
lblDate is a label into which the current date goes in.
That's a line of code that shows the current days date on a web page and it can easily "sit" inside an ASP website. If you want it to appear automatically, you may put that line of code in your Page_Load method.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
lblDate.Text = DateTime.Now.ToShortDateString
End Sub
The code is in VB.NET because I didn't see a tag for the code you're using. I think you'll get the gist of it though and you can use online converters to convert your code.

IIF statement to determine visibility of ImageButton in GridView not evaluating properly

I have a GridView that displays user info along with two template fields with imagebuttons. One is to open up a detailsview to edit user information. The other is to edit the user's password.
In my Code Behind, I have 3 IIf statements that check for certain criteria. Based on certain combinations of this criteria, I want the ImageButtons to either show/not show appropriately.
Here is my code behind:
Protected Sub gvUsers_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gvUsers.RowDataBound
Dim isProvisioned As Boolean
Dim acceptedToS As Boolean
Dim isSuspended As Boolean
'hide password change option for users that have not yet been provisioned or have not accepted ToS Agreement or have been suspended'
If e.Row.RowType = DataControlRowType.DataRow And _
DirectCast(sender, GridView).EditIndex <> e.Row.DataItemIndex Then
isProvisioned = IIf(String.IsNullOrEmpty(e.Row.DataItem(GUser.columns.DATEADDED).ToString), False, True)
acceptedToS = IIf(String.IsNullOrEmpty(e.Row.DataItem(GUser.columns.TOSTIMESTAMP).ToString), False, True)
isSuspended = IIf(String.IsNullOrEmpty(e.Row.DataItem(GUser.columns.SUSPENDDATE).ToString), False, True)
Dim btnAdminEdit As ImageButton = DirectCast(e.Row.FindControl("btnAdminEdit"), ImageButton)
Dim btnAdminSelect As ImageButton = DirectCast(e.Row.FindControl("btnAdminSelect"), ImageButton)
btnAdminEdit.Visible = Not (isSuspended) AndAlso isProvisioned AndAlso acceptedToS
btnAdminSelect.Visible = isProvisioned
Else
gvUsers.EmptyDataText = "No records found matching specified criteria."
End If
End Sub
I don't know what changed because this code DID work at one point. However, when I test the page, both imagebuttons seem to show up no matter what. While debugging, I also saw that it seemed to "evaluate" each row the same way. As in, for each row that went through my IIf statements, it always returned the same values, even if it was not true.
I have a hunch that it's taking the first row's values and reusing it some how, or evaluating the same row; that's why it always returns the same values and always shows the imagebuttons, even though they are not supposed to be visible according to my IIf statements.
Any help is greatly appreciated as I'm not too sure how to resolve it from here.
Well, after delving a little deeper, I found what was causing the problem.
The last change I made before seeing this problem was the addition of another column to be displayed in the GridView. This distorted the index of the columns so my IIF statements were not checking the correct datafields and thus, were evaluating incorrectly.
So, the code behind I posted does work and luckily proved that I wasn't going crazy. The logic is correct!
Thanks to those who took time to glance at this question!

Resources