How to download image/pdf file from database using Gridview's linkbutton? - asp.net

Here is my problem. I have a user control that will download a binary file (image, pdf etc.) using a link button in gridview.
<asp:GridView Visible="true" ID="GridView1" runat="server" HeaderStyle-BackColor="#3AC0F2" HeaderStyle-ForeColor="White"
RowStyle-BackColor="#A1DCF2" AlternatingRowStyle-BackColor="White" AlternatingRowStyle-ForeColor="#000"
AutoGenerateColumns="false">
<Columns>
<asp:BoundField DataField="ID" HeaderText="ID"/>
<asp:BoundField DataField="FileName" HeaderText="File Name"/>
<asp:TemplateField HeaderText="Action" ItemStyle-HorizontalAlign = "Center">
<ItemTemplate>
<asp:LinkButton ID="lnkDownload" runat="server" Text="Download" OnClick="DownloadFile" CommandArgument='<%# Eval("Id") %>'></asp:LinkButton>
<asp:LinkButton ID="lnkDelete" runat="server" Text="Delete" OnClick="DeleteFile" CommandArgument='<%# Eval("Id") %>'></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code Behind:
Protected Sub DownloadFile(sender As Object, e As EventArgs)
Dim id As Integer = Integer.Parse(TryCast(sender, LinkButton).CommandArgument)
Dim bytes As Byte()
Dim fileName As String, contentType As String
Using con As New SqlConnection(DataSource.ConnectionString)
Using cmd As New SqlCommand()
cmd.CommandText = "select FileName, PatImage, FileType from DB where Id=#Id"
cmd.Parameters.AddWithValue("#Id", id)
cmd.Connection = con
con.Open()
Using sdr As SqlDataReader = cmd.ExecuteReader()
sdr.Read()
bytes = DirectCast(sdr("PatImage"), Byte())
contentType = sdr("FileType").ToString()
fileName = sdr("FileName").ToString()
End Using
con.Close()
End Using
End Using
Response.Clear()
Response.Buffer = True
Response.Charset = ""
Response.Cache.SetCacheability(HttpCacheability.NoCache)
Response.ContentType = contentType
Response.AppendHeader("Content-Disposition", "attachment; filename=" + fileName)
Response.BinaryWrite(bytes)
Response.Flush()
Response.End()
End Sub
But this is not working if I have an UpdatePanel in my parent aspx page. So i googled and I found an answer; that is to place a code in RowDataBound:
Private Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowDataBound
Dim lb As LinkButton = TryCast(e.Row.FindControl("lnkDownload"), LinkButton )
ScriptManager.GetCurrent(Me.Page).RegisterAsyncPostBackControl(lb)
End Sub
And a new error occurred. That is I can't find my linkButton inside my GridView using my code in my RowDataBound.
So i googled again, and i found out that i should add a property to my aspx page ClientIDMode="AutoID". But this is only working on framework 4.x. And I couldn't do that 'cause im currently using 3.5. Are there any remedies in my current situation?

A already found an answer, I just changed my RowDataBound content, refer to the code:
Private Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
Dim LButton = CType(e.Row.FindControl("lnkDownload"), System.Web.UI.WebControls.LinkButton)
Dim scriptManager__1 = ToolkitScriptManager.GetCurrent(Me.Page)
If scriptManager__1 IsNot Nothing Then
scriptManager__1.RegisterPostBackControl(LButton)
End If
End If
End Sub

Related

Browse to a PDF in ASP.NET Web Site Folder

I have an ASP.NET Core web site running under IIS on a server. I created a folder and want to display any pdf file in that folder in the browser using the url for the site.
https://example.com/pdf/myfile.pdf
folder structure:
c:\inetpub\wwwroot\mysite\pdf\myfile.pdf - contains pdf files
I enabled Directory Browsing for the site in IIS Manager, but I get a 404 error.
I'm on Window Server 2019 IIS version 10.
I would dispense with folder/directory browsing. You can't control the user experince and UI.
And it just we few lines of code to display the files in a web page, and then have a button to display the pdf in the browser.
So our markup is like this:
<h2>Select a PDF file to view</h2>
<br />
<div style="width:45%">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" CssClass="table table-hover">
<Columns>
<asp:BoundField DataField="Date" HeaderText="Date" ItemStyle-Width="100px" />
<asp:BoundField DataField="File Name" HeaderText="ID" />
<asp:BoundField DataField="File Size" HeaderText="Size" ItemStyle-Width="100px" />
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="cmdDownLoad" runat="server" Text="View"
OnClick="cmdDownLoad_Click"
Row = '<%# Container.DataItemIndex %>'/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
And our code to pull files from a folder and shove into the above gridview looks like this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack = False Then
ShowFiles()
End If
End Sub
Sub ShowFiles()
Dim MyTable As New DataTable
MyTable.Columns.Add("Date", GetType(String))
MyTable.Columns.Add("File Size", GetType(String))
MyTable.Columns.Add("File Name", GetType(String))
MyTable.Columns.Add("FullFile", GetType(String))
'Dim strFolder = Server.MapPath("/app_data")
Dim strFolder = "c:\Test4"
Dim MyDir As New DirectoryInfo(strFolder)
Dim MyFiles() As FileInfo = MyDir.GetFiles("*.pdf")
For Each MyFile As FileInfo In MyFiles
Dim oneRow As DataRow = MyTable.Rows.Add
oneRow("Date") = MyFile.LastAccessTime.ToShortDateString
oneRow("File Size") = Int(MyFile.Length / 1024) & " KB"
oneRow("File Name") = MyFile.Name
oneRow("FullFile") = MyFile.FullName
Next
ViewState("MyTable") = MyTable
GridView1.DataSource = MyTable
GridView1.DataBind()
End Sub
The result is thus this:
So, now all we need is the button code to display the pdf in the browser.
This will work:
Protected Sub cmdDownLoad_Click(sender As Object, e As EventArgs)
Dim btn As Button = sender
Dim RowID = btn.Attributes.Item("Row")
Dim MyTable As DataTable = ViewState("MyTable")
With MyTable.Rows(RowID)
ShowPdf(.Item("File Name"), .Item("FullFile"))
End With
End Sub
Sub ShowPdf(strFileOnlyName As String, strFile As String)
Dim pDFData As Byte()
pDFData = File.ReadAllBytes(strFile)
Response.Buffer = False ' //transmitfile self buffers
Response.Clear()
Response.ClearContent()
Response.ClearHeaders()
Response.AddHeader("Accept-Header", pDFData.Length.ToString())
Response.AddHeader("Content-Length", pDFData.Length.ToString())
Response.AddHeader("Content-Disposition", "inline; filename=" & strFileOnlyName)
Response.AddHeader("Expires", "0")
Response.AddHeader("Cache-Control", "private")
Response.ContentType = "application/pdf"
Response.AddHeader("Accept-Ranges", "bytes")
Response.BinaryWrite(pDFData)
Response.Flush()
Response.End()
End Sub
So you can click on the button - it will display the PDF in the browser. If you hit back, then you back to the grid, and you can then view another file.

copy row from asp.net gridview to new page using VB

I am trying to copy a row from a gridview to be displayed on a new page through a button in one of the columns in the gridview. I have my gridview populated from an Access database that is linked to my project. I have tried several different things, but nothing will display the row information when the project is ran. The current code I am trying from the actual dataview is:
Example 1a
<asp:GridView ID="Grid1" runat="server" Width ="90%" AutoGenerateColumns="false" OnRowDeleting="Grid1_RowDeleting" DataKeyNames="Title">
<Columns>
<asp:BoundField DataField="Title" HeaderText="Title" />
<asp:BoundField DataField="Console" HeaderText="Console" />
<asp:BoundField DataField="Year_Released" HeaderText="Year Released" />
<asp:BoundField DataField="ESRB" HeaderText="ESRB Rating" />
<asp:BoundField DataField="Score" HeaderText="Personal Score" />
<asp:BoundField DataField="Publisher" HeaderText="Publisher" />
<asp:BoundField DataField="Developer" HeaderText="Developer" />
<asp:BoundField DataField="Genre" HeaderText="Genre" />
<asp:BoundField DataField="Purchase" HeaderText="Purchase Date" />
<asp:TemplateField ItemStyle-Width="7%" ShowHeader="False">
<ItemTemplate>
<asp:LinkButton ID="lnkDetails" runat="server" Text="View" PostBackUrl='<%# "~/ViewDetails.aspx?RowIndex=" & Container.DataItemIndex %>'/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And the codebehind code on the page where I am trying to have the code be displayed is:
Example 1b
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
If Me.Page.PreviousPage IsNot Nothing Then
Dim rowIndex As Integer = Integer.Parse(Request.QueryString("RowIndex"))
Dim GridView1 As GridView = DirectCast(Me.Page.PreviousPage.FindControl("Grid1"), GridView)
Dim row As GridViewRow = GridView1.Rows(rowIndex)
lblTitle.Text = row.Cells(0).Text
lblConsole.Text = row.Cells(1).Text
lblYear.Text = row.Cells(2).Text
lblESRB.Text = row.Cells(3).Text
lblScore.Text = row.Cells(4).Text
lblPublisher.Text = row.Cells(5).Text
lblDeveloper.Text = row.Cells(6).Text
lblGenre.Text = row.Cells(7).Text
lblPurchase.Text = row.Cells(8).Text
End If
End Sub
I have also tried another set of code where the button on the gridview was:
Example 2a
<asp:Button ID="btnLink" runat="server" Text="View Details" PostBackUrl='<%# Eval("Title", "~/ViewDetails.aspx?Id={0}") %>'/>
Where the codebehind code is:
Example 2b
Protected Sub Page_Load(sender As Object, e As EventArgs)
If Not IsPostBack Then
Dim GameTitle As String = Request.QueryString("Id")
Dim connString As String = "PROVIDER=Microsoft.ACE.OLEDB.12.0;" + "DATA SOURCE=" + Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "App_Data" + "db1.accdb")
Using connection As New OleDbConnection(connString)
connection.Open()
Dim reader As OleDbDataReader = Nothing
Dim command As New OleDbCommand((Convert.ToString("SELECT * from [Video_Games] WHERE Title='") & GameTitle) + "'", connection)
reader = command.ExecuteReader()
While reader.Read()
lblTitle.Text = reader(0).ToString()
lblConsole.Text = reader(1).ToString()
lblYear.Text = reader(2).ToString()
lblESRB.Text = reader(3).ToString()
lblScore.Text = reader(4).ToString()
lblPublisher.Text = reader(5).ToString()
lblDeveloper.Text = reader(6).ToString()
lblGenre.Text = reader(7).ToString()
lblPurchase.Text = Convert.ToDateTime(reader(8).ToString()).ToShortDateString()
End While
End Using
End If
End Sub
End Class
I have tried making variations of both, mainly the second, but whatever I try the labels are not populated with the row information. Any assistance would be appreciated, and I can post any other code needed, like how I populated the gridview. Thank you.
It was as simple as changing the AutoEventWireup to "true" in my .aspx file.

Gridview: editing after searching

MY search button is linked to a GridvieW, which has an edit button on every row. When I press search button, data changes and a databind() occurs.
After that, If I try to use the edit button it displays another row to edit, not the selected one(biggest problem).Both buttons work well when tested separately, but not one after another. I solved that removing GridView1.DataBind() from edit button event, but then It will require 2 clicks to display the edit template(another problem).
EDIT: I guess teh problem is in the search button. Can you give a good search code that doesn't depend of sqldatasource?
'Where data is loaded into GV
Dim SqlDataSource1 As New SqlDataSource
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
SqlDataSource1.SelectCommand = "SELECT * FROM [TABLE]"
SqlDataSource1.ConnectionString = "Conn String"
If Not IsPostBack Then
Dim conn As New SqlConnection
conn.ConnectionString = con.GetConnectionString
Dim cmd As New SqlCommand()
cmd.CommandText = "SELECT [AREA], [LEADER_USER] FROM [AREA]"
cmd.CommandType = CommandType.Text
cmd.Connection = conn
conn.Open()
Dim adpt As New SqlDataAdapter(cmd)
Dim ds As New DataSet()
adpt.Fill(ds)
GridView1.DataSource = ds
GridView1.DataBind()
conn.Close()
End If
End Sub
'Search button
Protected Sub btnSearch_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSearch.Click
Try
SqlDataSource1.SelectCommand = "SELECT * FROM TABLE WHERE id LIKE #id"
SqlDataSource1.SelectParameters.Clear()
SqlDataSource1.SelectParameters.Add(New Parameter("id", DbType.String, "%" + txtSearch.Text + "%"))
GridView1.DataSource = SqlDataSource1
GridView1.DataBind()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
'Edit button
Protected Sub EditRow(ByVal sender As Object, ByVal e As GridViewEditEventArgs)
GridView1.EditIndex = e.NewEditIndex
GridView1.DataSource = SqlDataSource1
GridView1.DataBind()
End Sub
Markup:
<asp:TextBox ID="TextBox1" runat="server" BackColor="#D9ECFF"
style="height: 20px; width: 186px" AutoPostBack="True"></asp:TextBox>
<asp:Button ID="btnSearch" runat="server" BackColor="#0066cc"
BorderColor="#0066cc" BorderStyle="Outset" Font-Bold="True" ForeColor="White"
style=" height: 26px; width: 56px" Text="Search" />
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" AllowSorting="True"
AutoGenerateColumns="False" CellPadding="4" OnRowEditing="EditRow"
OnRowCancelingEdit="CancelEditRow" DataKeyNames="AREA" DataMember="DefaultView">
<Columns>
<asp:BoundField DataField="AREA" HeaderText="AREA" ReadOnly="True"
SortExpression="AREA" />
<asp:TemplateField HeaderText="LEADER_USER" SortExpression="LEADER_USER">
<ItemTemplate><%#Eval("leader_user")%></ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtleaderuser" runat="server" Text='<%#Eval("leader_user")%>'/>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:ImageButton ID="editButton" runat="server" CommandName="Edit"
ImageUrl="images/pencil1.png" Text="Edit" ToolTip="Edit" />
</ItemTemplate>
<EditItemTemplate>
<asp:Button ID="BtnUpdate" runat="server" CommandName="Update"
Text="Update" />
<asp:Button ID="BtnCancel" runat="server" CommandName="Cancel"
Text="Cancel" />
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Please help me. How are these 2 gridview functionalities supposed to be coded to work together? This is the only way I know how to do this, but any idea is ok for me if it works. If you are a C# guy, you ca use a C#-to VB converter:
http://www.developerfusion.com/tools/convert/csharp-to-vb/
Try this :
fill_grid()
{
// populate your grid
SqlCommand cmd = new SqlCommand();
cmd.CommandText = " your select statement ";
cmd.CommandType = CommandType.Text;
cmd.Connection = this.sqlConnection1;
this.yourConnection .Open();
SqlDataAdapter adpt = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
adpt.Fill(ds);
yourGrid.DataSource = ds;
yourGrid.DataBind();
this.sqlConnection1.Close();
}
Then hook to the button click event of your search button like this :
yourButton_Click ((object sender, EventArgs e)
{
GridViewRow clickedRow = ((Button)sender).NamingContainer as GridViewRow;
//Then find your parameter from your textbox in the clicked row
TextBox yourbox = (TextBox)clickedRow.FindControl("your_box");
//Here is where you would all your search logic whatever that is
}
Then you could still use your row_updating event independently of the search button click event.
you can add Where statement in page_load by if command and delete where in btnSearch_Click function. like this
if (txtSearch.Text.length()>0)
SqlDataSource1.SelectCommand += "WHERE id LIKE #id"
then it works properly

why button click insert data twice

i have this button which i add in row of data however, i only add two row of the date, when click this button it give me 4 data, each date is being inserted twice meaning date A den date B den date A and den date B, what the problem
Protected Sub Button2_Click(sender As Object, e As System.EventArgs) Handles Button2.Click
Dim rowIndex As Integer = 0
Dim sc As New StringCollection()
Dim sc1 As New Date
If ViewState("CurrentTable") IsNot Nothing Then
Dim dtCurrentTable As DataTable = DirectCast(ViewState("CurrentTable"), DataTable)
Dim drCurrentRow As DataRow = Nothing
If dtCurrentTable.Rows.Count < 10 Then
For i As Integer = 1 To dtCurrentTable.Rows.Count
'extract the TextBox values
Dim box5 As TextBox = DirectCast(Gridview3.Rows(rowIndex).Cells(1).FindControl("TextBox5"), TextBox)
Dim box7 As Date = Convert.ToDateTime(box5.Text)
Dim myConn As New SqlConnection
Dim myCmd As New SqlCommand
myConn.ConnectionString = ConfigurationManager.ConnectionStrings("mydatabase").ConnectionString
Dim cmd As String
cmd = "Insert into Date values (#date) "
myCmd.CommandText = cmd
myCmd.CommandType = CommandType.Text
myCmd.Parameters.Add(New SqlParameter("#date", box7))
myCmd.Connection = myConn
myConn.Open()
myCmd.ExecuteNonQuery()
myCmd.Dispose()
myConn.Dispose()
rowIndex += 1
Next
End If
Else
' lblMessage.Text = "Cannot save as there no information recorded"
MsgBox("failed")
End If
End Sub
<asp:GridView ID="Gridview3" runat="server" AutoGenerateColumns="False"
Height="89px" ShowFooter="True" Width="303px">
<Columns>
<asp:BoundField DataField="RowNumber" HeaderText="No of Available:" />
<asp:TemplateField HeaderText="New Date Available :">
<ItemTemplate>
<asp:TextBox ID="TextBox5" runat="server" />
<AjaxToolkit:CalendarExtender ID="calExtender6" runat="server"
Format="dd/MM/yyyy" OnClientDateSelectionChanged="CheckDateEalier"
TargetControlID="TextBox5" />
</ItemTemplate>
<FooterStyle Height="22px" HorizontalAlign="Right" />
<FooterTemplate>
<asp:Button ID="ButtonAdd" runat="server" onclick="ButtonAdd_Click"
Text="Add New Row" />
</FooterTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView> 
Protected Sub ButtonAdd_Click(sender As Object, e As System.EventArgs)
AddNewRowToGrid()
End Sub
You called the function twice, once when you declare "Handles Button2.Click" and second when you set the onclick="ButtonAdd_Click".
You need to choose one of the options.
Hope that's help
Please check in the view page. I have experienced a similar issue like this in my struts,spring,hibernate application. My action method was called twice. This is because i have give the tag for the button as submit. something like <button:submit... . Just ensure that your method is called once or twice.
I had a similar problem, I created another button and copied all codes of the first button and inserted behind the new button, now the problem has solved.
it worked for me.

Gridview rowdatabound access data items vb

I am trying to an ImageUrl to an image in a Template Field in GridView but keep getting the error:
Object reference not set to an instance of an object. on this line:
Dim imagePath As String = rowView("image_path")
I've never done this before on a GridView but had it working on a ListView.
Thanks for any help heres my code:
.APSX
<asp:GridView ID="gvImages" DataKeyNames="id" runat="server" AutoGenerateColumns="False" BorderWidth="0px" GridLines="None">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="imageId" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:Image ID="imageFile" runat="server"></asp:Image>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="id" />
</Columns>
</asp:GridView>
CODE BEHIND
Protected Sub gvImages_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gvImages.RowDataBound
Dim rowView As DataRowView = CType(e.Row.DataItem, DataRowView)
Dim imagePath As String = rowView("image_path")
Dim strImageUrl As String = "~/admin/images/cases/" & Request.QueryString("uid") & "/" & imagePath
Dim imageFile As System.Web.UI.WebControls.Image = CType(e.Row.FindControl("imageFile"), System.Web.UI.WebControls.Image)
imageFile.ImageUrl = strImageUrl
End Sub
I think you need to check that its a data row and not the header row
Try this
Protected Sub gvImages_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gvImages.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
Dim rowView As DataRowView = CType(e.Row.DataItem, DataRowView)
Dim imagePath As String = rowView("image_path")
Dim strImageUrl As String = "~/admin/images/cases/" & Request.QueryString("uid") & "/" & imagePath
Dim imageFile As System.Web.UI.WebControls.Image = CType(e.Row.FindControl("imageFile"), System.Web.UI.WebControls.Image)
imageFile.ImageUrl = strImageUrl
End If
End Sub
try
Dim imagePath As String = e.rowView("image_path").ToString()
If the table binded with the grid has column "image_path", then instead use an easier way....
<asp:Image id="img1" runat="server" imageUrl = '<%#Eval("image_path")%>' />
If you want to build some custome string
imageurl = '<%# String.Format("{0} - {1} - {2} - {3}", Eval("Name1"), Eval("Name2"), Session["abc"],Request["abc"]) %>'

Resources