I'm trying to download files from an SQL Server 2012 database using GridView. I am getting an ArgumentOutOfRangeException giving me this error:
Index was out of range. Must be non-negative and less than the size of the collection.
on:
Dim fileid As Integer = Convert.ToInt32(GridView1.DataKeys(gvrow.RowIndex).Value.ToString())
Code concerned:
Protected Sub lnkDownload_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim lnkbtn As LinkButton = TryCast(sender, LinkButton)
Dim gvrow As GridViewRow = TryCast(lnkbtn.NamingContainer, GridViewRow)
Dim fileid As Integer = Convert.ToInt32(GridView1.DataKeys(gvrow.RowIndex).Value.ToString())
Dim name As String, type As String
Dim con As New SqlConnection("Data Source=BRIAN-PC\SQLEXPRESS;Initial Catalog=master_db;Integrated Security=True;")
con.Open()
Using cmd As New SqlCommand()
cmd.CommandText = "Select content_name, content_type, content_file from content where content_id=#Id"
cmd.Parameters.AddWithValue("#Id", fileid)
cmd.Connection = con
con.Open()
Dim dt As DataTable = GetData(cmd)
If dt IsNot Nothing Then
download(dt)
End If
End Using
End Sub
Public Function GetData(ByVal cmd As SqlCommand) As DataTable
Dim dt As New DataTable
Dim strConnString As String = System.Configuration.ConfigurationManager.ConnectionStrings("ConnStringDb1").ConnectionString()
Dim con As New SqlConnection(strConnString)
Dim sda As New SqlDataAdapter
cmd.CommandType = CommandType.Text
cmd.Connection = con
Try
con.Open()
sda.SelectCommand = cmd
sda.Fill(dt)
Return dt
Catch ex As Exception
Response.Write(ex.Message)
Return Nothing
Finally
con.Close()
sda.Dispose()
con.Dispose()
End Try
End Function
Protected Sub download(ByVal dt As DataTable)
Dim bytes() As Byte = CType(dt.Rows(0)("Data"), Byte())
Response.Buffer = True
Response.Charset = ""
Response.Cache.SetCacheability(HttpCacheability.NoCache)
Response.ContentType = dt.Rows(0)("ContentType").ToString()
Response.AddHeader("content-disposition", "attachment;filename=" & dt.Rows(0)("Name").ToString())
Response.BinaryWrite(bytes)
Response.Flush()
Response.End()
End Sub
gvrow.RowIndex at time of debugging is 0.
Full Code:
Imports System.Data.SqlClient
Imports System.Data
Imports System.IO
Partial Class Documents
Inherits System.Web.UI.Page
Protected Sub btnUploadContent_Click(sender As Object, e As EventArgs) Handles btnUploadContent.Click
Dim filePath As String = FileUpload.PostedFile.FileName
Dim filename As String = Path.GetFileName(filePath)
Dim ext As String = Path.GetExtension(filename)
Dim contenttype As String = String.Empty
Select Case ext
Case ".doc"
contenttype = "application/vnd.ms-word"
Exit Select
Case ".docx"
contenttype = "application/vnd.ms-word"
Exit Select
Case ".xls"
contenttype = "application/vnd.ms-excel"
Exit Select
Case ".xlsx"
contenttype = "application/vnd.ms-excel"
Exit Select
Case ".jpg"
contenttype = "image/jpg"
Exit Select
Case ".png"
contenttype = "image/png"
Exit Select
Case ".gif"
contenttype = "image/gif"
Exit Select
Case ".pdf"
contenttype = "application/pdf"
Exit Select
End Select
If contenttype <> String.Empty Then
Dim fs As Stream = FileUpload.PostedFile.InputStream
Dim br As New BinaryReader(fs)
Dim bytes As Byte() = br.ReadBytes(fs.Length)
'insert the file into database
Dim strQuery As String = "INSERT INTO [master_db].[dbo].[content] ([content_name],[content_type],[content_file]) VALUES (#Name, #ContentType, #Data)"
Dim cmd As New SqlCommand(strQuery)
cmd.Parameters.Add("#Name", SqlDbType.VarChar).Value = filename
cmd.Parameters.Add("#ContentType", SqlDbType.VarChar).Value() = contenttype
cmd.Parameters.Add("#Data", SqlDbType.Binary).Value = bytes
InsertUpdateData(cmd)
lblMessage.ForeColor = System.Drawing.Color.Green
lblMessage.Text = "File Uploaded Successfully"
Else
lblMessage.ForeColor = System.Drawing.Color.Red
lblMessage.Text = "File format not recognised." + " Upload Image/Word/PDF/Excel formats"
End If
End Sub
Protected Sub lnkDownload_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim lnkbtn As LinkButton = TryCast(sender, LinkButton)
Dim gvrow As GridViewRow = TryCast(lnkbtn.NamingContainer, GridViewRow)
Dim fileid As Integer = Convert.ToInt32(GridView1.DataKeys(gvrow.RowIndex).Value.ToString())
Dim name As String, type As String
Dim con As New SqlConnection("Data Source=BRIAN-PC\SQLEXPRESS;Initial Catalog=master_db;Integrated Security=True;")
con.Open()
Using cmd As New SqlCommand()
cmd.CommandText = "Select content_name, content_type, content_file from content where content_id=#Id"
cmd.Parameters.AddWithValue("#Id", fileid)
cmd.Connection = con
con.Open()
Dim dt As DataTable = GetData(cmd)
If dt IsNot Nothing Then
download(dt)
End If
End Using
End Sub
Public Function GetData(ByVal cmd As SqlCommand) As DataTable
Dim dt As New DataTable
Dim strConnString As String = System.Configuration.ConfigurationManager.ConnectionStrings("ConnStringDb1").ConnectionString()
Dim con As New SqlConnection(strConnString)
Dim sda As New SqlDataAdapter
cmd.CommandType = CommandType.Text
cmd.Connection = con
Try
con.Open()
sda.SelectCommand = cmd
sda.Fill(dt)
Return dt
Catch ex As Exception
Response.Write(ex.Message)
Return Nothing
Finally
con.Close()
sda.Dispose()
con.Dispose()
End Try
End Function
Protected Sub download(ByVal dt As DataTable)
Dim bytes() As Byte = CType(dt.Rows(0)("Data"), Byte())
Response.Buffer = True
Response.Charset = ""
Response.Cache.SetCacheability(HttpCacheability.NoCache)
Response.ContentType = dt.Rows(0)("ContentType").ToString()
Response.AddHeader("content-disposition", "attachment;filename=" & dt.Rows(0)("Name").ToString())
Response.BinaryWrite(bytes)
Response.Flush()
Response.End()
End Sub
Public Function InsertUpdateData(ByVal cmd As SqlCommand) As Boolean
Dim strConnString As String = System.Configuration.ConfigurationManager.ConnectionStrings("ConnStringDb1").ConnectionString()
Dim conn As New SqlConnection("Data Source=BRIAN-PC\SQLEXPRESS;Initial Catalog=master_db;Integrated Security=True;")
cmd.CommandType = CommandType.Text
cmd.Connection = conn
Try
conn.Open()
cmd.ExecuteNonQuery()
Return True
Catch ex As Exception
Response.Write(ex.Message)
Return False
Finally
conn.Close()
conn.Dispose()
End Try
End Function
End Class
What is happening and why?
replace the error line with this:
Dim selectedRow As Integer = Me.GridView1.CurrentRow.Index
Dim fileid As Integer = Convert.ToInt32(Me.GridView1.Item(1,gvrow.RowIndex).Value.ToString())
Replace the number 1 with the index of the cell that contains the fileid (ie if its the 0 for the first cell, 1 for the second and so on)
Let me know if this works. Am a C# developer so conversions may differ.
pass the RowIndex via CommandArgument and use it to retrieve the DataKey value
add the below line on Button
CommandArgument='<%# DataBinder.Eval(Container, "RowIndex") %>'
and add the below line on Server Event
Dim Index As Integer = Integer.Parse(e.CommandArgument.ToString())
Dim val As String = DirectCast(Me.grid.DataKeys(Index)("YourDataKeyName"), String)
Update:
See this samples :
sample1
sample 2
I ran into this a while ago myself replacing a predecessors data adapter's with data readers for obvious reasons.
My fix was simple:
if (dt.Rows.Count == 0)
//do stuff
else
//do nothing
GV.DataSource = new DataTable();
you're also loading with a datatable, so that should make deploying it easier.
The reason in your specific case is the exception is thrown when no data is passed to the GV.
Related
Here's my code:
Partial Class VideoPlayer
Inherits System.Web.UI.Page
Protected strFileName As String
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
Dim con As New OleDbConnection
Dim dbProvider As String
Dim dbSource As String
Dim vidID As Integer = Integer.Parse(Request.QueryString("ID"))
dbProvider = "PROVIDER=Microsoft.Jet.OLEDB.4.0;"
dbSource = "Data Source = |DataDirectory|/webvideos.mdb"
con.ConnectionString = dbProvider & dbSource
con.Open()
Dim strSQL As String = "SELECT * FROM Videos WHERE ID=" & vidID
strFileName = "videos/TrainingVideos/" & Eval("Filename")
con.Close()
End Sub
End Class
So when I run the code, it tells me it can't run Eval on my string. What am I missing?
Eval will work in your .aspx code with a DataBoundControl.
When in code-behind, you are setting up the connectionstring, sql query and other variables but you are not actually executing the query.
So your code should be something like below:
Dim con As New OleDbConnection
Dim dbProvider As String
Dim dbSource As String
Dim vidID As Integer = Integer.Parse(Request.QueryString("ID"))
dbProvider = "PROVIDER=Microsoft.Jet.OLEDB.4.0;"
dbSource = "Data Source = |DataDirectory|/webvideos.mdb"
con.ConnectionString = dbProvider & dbSource
con.Open()
Dim strSQL As String = "SELECT * FROM Videos WHERE ID=" & vidID
//Create an OleDbCommand object.
//Pass in the SQL query and the OleDbConnection object
Dim cmd As OleDbCommand = New OleDbCommand(strSQL, con)
//Execute the command
Dim reader As OleDbDataReader = cmd.ExecuteReader
//Read the first record from the reader
reader.Read()
strFileName = "videos\TrainingVideos\" & reader(1)
con.Close()
First the most important, you are open for sql-injection here:
"SELECT * FROM Videos WHERE ID=" & vidID
Use sql-parameters instead.
You can use Eval only in a databinding context. So you need to call Me.DataBind before.
Me.DataBind()
Dim fileName = Me.Eval("Filename").ToString()
strFileName = System.IO.Path.Combine("videos/TrainingVideos", fileName)
However, i don't know what you're actually trying to achieve here. Why do you need it at all?
Global variable, forgot to add it up there.
Then access it directly.
I'm trying to download a file from an SQL Server table. I am using a GridView. Whenever I try to download a file, I get a corrupted file.
I am using ASP.NET and VB.NET with SQL Server 2012 Express.
Any ideas why ?
Protected Sub GridView1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles GridView1.SelectedIndexChanged
Dim ContentID = Convert.ToInt32(GridView1.SelectedRow.Cells(1).Text)
Dim ContentName = GridView1.SelectedRow.Cells(2).Text
Dim ContentType = GridView1.SelectedRow.Cells(3).Text
lblContentName.Text = "[ " + ContentName + " ]"
lblContentName.Visible = True
End Sub
Protected Sub GridView1_RowCommand(sender As Object, e As GridViewCommandEventArgs)
Dim cn As New SqlConnection("Data Source=BRIAN-PC\SQLEXPRESS;Initial Catalog=master_db;Integrated Security=True;")
If e.CommandName = "Download" Then
Dim filename As String = String.Empty
Dim id As Integer = Convert.ToInt32(e.CommandArgument)
Dim cmd As New SqlCommand("SELECT content_name,content_type,content_data FROM content WHERE content_id = " & id, cn)
cn.Open()
Dim dr As SqlDataReader = cmd.ExecuteReader
Dim bytes As Byte()
dr = cmd.ExecuteReader()
If dr.Read() Then
filename = dr("content_name").ToString()
Response.ContentType = dr("content_type").ToString()
Response.AddHeader("Content-Disposition", "attachment;filename=" & filename)
bytes = DirectCast(dr("content_file"), Byte())
Response.Cache.SetCacheability(HttpCacheability.NoCache)
Response.BinaryWrite(bytes)
Response.Flush()
Response.[End]()
End If
End If
End Sub
Private Sub BindGrid()
Dim constr As String = ConfigurationManager.ConnectionStrings("ConnStringDb1").ConnectionString
Using con As New SqlConnection(constr)
Using cmd As New SqlCommand()
cmd.CommandText = "SELECT content_id, content_name FROM content"
cmd.Connection = con
con.Open()
GridView1.DataSource = cmd.ExecuteReader()
GridView1.DataBind()
con.Close()
End Using
End Using
End Sub
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
If Not IsPostBack Then
BindGrid()
End If
End Sub
I followed a tutorial an ran the below code without any errors. The file "uploads", however no data is inserted into my SQL Server table.
Data should be inserted into the content table.
Content Table:
Document.aspx
Imports System.Data.SqlClient
Imports System.Data
Imports System.IO
Partial Class Documents
Inherits System.Web.UI.Page
Protected Sub btnUploadContent_Click(sender As Object, e As EventArgs) Handles btnUploadContent.Click
Dim filePath As String = FileUpload.PostedFile.FileName
Dim filename As String = Path.GetFileName(filePath)
Dim ext As String = Path.GetExtension(filename)
Dim contenttype As String = String.Empty
Select Case ext
Case ".doc"
contenttype = "application/vnd.ms-word"
Exit Select
Case ".docx"
contenttype = "application/vnd.ms-word"
Exit Select
Case ".xls"
contenttype = "application/vnd.ms-excel"
Exit Select
Case ".xlsx"
contenttype = "application/vnd.ms-excel"
Exit Select
Case ".jpg"
contenttype = "image/jpg"
Exit Select
Case ".png"
contenttype = "image/png"
Exit Select
Case ".gif"
contenttype = "image/gif"
Exit Select
Case ".pdf"
contenttype = "application/pdf"
Exit Select
End Select
If contenttype <> String.Empty Then
Dim fs As Stream = FileUpload.PostedFile.InputStream
Dim br As New BinaryReader(fs)
Dim bytes As Byte() = br.ReadBytes(fs.Length)
'insert the file into database
Dim strQuery As String = "INSERT INTO content (content_name, content_type, content_file) VALUES (#Name, #ContentType, #Data)"
Dim cmd As New SqlCommand(strQuery)
cmd.Parameters.Add("#Name", SqlDbType.VarChar).Value = filename
cmd.Parameters.Add("#ContentType", SqlDbType.VarChar).Value() = contenttype
cmd.Parameters.Add("#Data", SqlDbType.Binary).Value = bytes
InsertUpdateData(cmd)
lblMessage.ForeColor = System.Drawing.Color.Green
lblMessage.Text = "File Uploaded Successfully"
Else
lblMessage.ForeColor = System.Drawing.Color.Red
lblMessage.Text = "File format not recognised." + " Upload Image/Word/PDF/Excel formats"
End If
End Sub
Public Function InsertUpdateData(ByVal cmd As SqlCommand) As Boolean
Dim strConnString As String = System.Configuration.ConfigurationManager.ConnectionStrings("ConnStringDb1").ConnectionString()
Dim conn As New SqlConnection("Data Source=BRIAN-PC\SQLEXPRESS;Initial Catalog=master_db;Integrated Security=True;")
cmd.CommandType = CommandType.Text
cmd.Connection = conn
Try
conn.Open()
cmd.ExecuteNonQuery()
Return True
Catch ex As Exception
Response.Write(ex.Message)
Return False
Finally
conn.Close()
conn.Dispose()
End Try
End Function
End Class
Can anyone tell me what's going on ?
EDIT: Debug Breakpoint # InsertUpdateData(cmd) :
SqlDbType.Binary Binary {1} System.Data.SqlDbType
+ bytes {Length=4136752} Byte()
+ cmd {System.Data.SqlClient.SqlCommand} System.Data.SqlClient.SqlCommand
+ cmd.Parameters {System.Data.SqlClient.SqlParameterCollection} System.Data.SqlClient.SqlParameterCollection
I have created empty database and added table content just like you have and I used code almost the same as you and it worked fine.
Again, if no exception occurs, please check your connection string and see whether the rows been added to the table in the db specified in connection string.
Here is my code (which is working fine), a bit modified from yours:
Imports System.Data.SqlClient
Imports System.IO
Public Class _Default
Inherits System.Web.UI.Page
Protected Sub btnUploadContent_Click(sender As Object, e As EventArgs) Handles btnTest1.Click
Dim fs As Stream = FileUpload.PostedFile.InputStream
Dim br As New BinaryReader(fs)
Dim bytes As Byte() = br.ReadBytes(fs.Length)
'insert the file into database
Dim strQuery As String = "INSERT INTO content (content_name, content_type, content_file) VALUES (#Name, #ContentType, #Data)"
Dim cmd As New SqlCommand(strQuery)
cmd.Parameters.Add("#Name", SqlDbType.VarChar).Value = "filename"
cmd.Parameters.Add("#ContentType", SqlDbType.VarChar).Value() = "jpg"
cmd.Parameters.Add("#Data", SqlDbType.Binary).Value = bytes
InsertUpdateData(cmd)
End Sub
Public Function InsertUpdateData(ByVal cmd As SqlCommand) As Boolean
Dim conn As New SqlConnection("Data Source=(local);Initial Catalog=test;Integrated Security=True;")
cmd.CommandType = CommandType.Text
cmd.Connection = conn
Try
conn.Open()
cmd.ExecuteNonQuery()
Return True
Catch ex As Exception
Response.Write(ex.Message)
Return False
Finally
conn.Close()
conn.Dispose()
End Try
End Function
End Class
I add sample of SQL to test on DB:
INSERT INTO [master_db].[dbo].[content]
([content_name]
,[content_type]
,[content_file])
VALUES
('test'
,'png'
,0x111111111111111)
SELECT * FROM [master_db].[dbo].[content]
I came across this post looking looking for an example. I used the example code you posted and had the same problem. I found and resolved the following issues and got it working:
I created the db table as pictured. content_type of nchar(5) was the first problem since you were inserting something like "application/vnd.ms-word" which was too big.
The next error was because I had not defined the content_id to be an identity column and since it wasn't listed in the insert statement it failed.
Next I had an error as my db user didn't have insert privileges.
The biggest problem is that the return message was always a success message because even though the InsertUpdateData function was catching errors it was not notifying the calling code. This made me think things were okay. doh! Using a breakpoint on the ExecuteNonQuery allowed me to see the errors.
Hope that helps the next person that stops by....
I am trying to work out SQL code in VB but I am having problems I have a simple database with the table admin with the columns UserName and Password.
I want to be able to read data from a text box and then input it into a SQL string… the SQL string works (I've tested it) and I can get it to output with a simple SELECT statement but I can't seem to get the SQL to read my Parameter.
Help?
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Call Password_Check(txtTestInput.Text)
End Sub
Public Sub Password_Check(ByVal Answer As String)
Dim con As New SqlConnection
Dim cmd As New SqlCommand
Dim parameter As New SqlParameter("#Username", Answer)
Try
con.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings("Database1ConnectionString1").ConnectionString
con.Open()
cmd.Connection = con
cmd.CommandText = " SELECT Password FROM Admin WHERE (UserName = #Username)"
cmd.Parameters.Add(parameter)
Dim lrd As SqlDataReader = cmd.ExecuteReader()
While lrd.Read()
Dim sothing As String
sothing = lrd("Password").ToString
If lrd("Password").ToString = txtPassword.Text Then
lblTestData.Text = "passwordSuccess"
ElseIf lrd("Password").ToString <> txtPassword.Text Then
lblTestData.Text = "passwordFail...:("
End If
End While
Catch ex As Exception
lblTestData.Text = "Error while retrieving records on table..." & ex.Message
Finally
con.Close()
End Try
End Sub
in your code above:
--> Dim parameter As New SqlParameter("#Username", Answer)
Can I suggest two options:
Dim parameter As New SqlParameter("#Username", sqldbtype.nvarchar)
parameter.value = Answer
or
cmd.CommandText = string.format("SELECT Password FROM Admin WHERE (UserName = {0})", Answer)
Full Code:
Public Sub Password_Check(ByVal Answer As String)
Dim con As New SqlConnection
Dim cmd As New SqlCommand
Dim parameter As New SqlParameter("#Username", SqlDbType.NVarChar)
parameter.Value = Answer
Try
con.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings("Database1ConnectionString1").ConnectionString
con.Open()
cmd.Connection = con
cmd.CommandText = "SELECT Password FROM Admin WHERE (UserName = #Username)"
cmd.Parameters.Add(parameter)
Dim lrd As SqlDataReader = cmd.ExecuteReader()
While lrd.Read()
Dim sothing As String
sothing = lrd("Password").ToString
If lrd("Password").ToString = txtPassword.Text Then
lblTestData.Text = "passwordSuccess"
ElseIf lrd("Password").ToString <> txtPassword.Text Then
lblTestData.Text = "passwordFail...:("
End If
End While
Catch ex As Exception
lblTestData.Text = "Error while retrieving records on table..." & ex.Message
Finally
con.Close()
End Try
End Sub
Regarding to your Database system it is possible that it does not support parameter names. Have you tried ? Wat DB System you used?
cmd.CommandText = " SELECT Password FROM Admin WHERE (UserName = ?)"
Protected Sub Login1_Authenticate(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.AuthenticateEventArgs) Handles Login1.Authenticate
Dim Uname As String
Dim pwd As String
Dim pName As String
Dim reader As SqlDataReader
Uname = Login1.UserName
pwd = Login1.Password
pName = ""
Dim strConn As String
strConn = WebConfigurationManager.ConnectionStrings("ConnectionASPX").ConnectionString
Dim Conn As New SqlConnection(strConn)
Conn.Open()
Dim sqlUserName As String
sqlUserName = "SELECT UserName,Password FROM Customer"
sqlUserName &= " WHERE (UserName = #Uname"
sqlUserName &= " AND Password = #Pwd)"
Dim com As New SqlCommand(sqlUserName, Conn)
com.Parameters.AddWithValue("#Uname", Uname)
com.Parameters.AddWithValue("#Pwd", pwd)
reader = com.ExecuteReader()
If (reader.Read()) Then
Me.Response.Redirect("Faq.aspx")
Else
MsgBox("Invalid UserName-password")
End If
reader.Close()
Conn.Close()
'If CurrentName <> "" Then
' Session("UserAuthentication") = Uname
' Response.Redirect("Faq.aspx")
'Else
' Session("UserAuthentication") = ""
'End If
End Sub
the code kis working without any errors . It is not redirecting to another page.
Put a breakpoint (press F9) on the line If (reader.Read()) Then and then press F5 to run the app in debug mode and step through that line to see if it is skipping your Response.Redirect call. If it is, you will have to figure out why the Read() method is returning false.