Link to home
Start Free TrialLog in
Avatar of rkulp
rkulpFlag for United States of America

asked on

Displaying a PDF File in ASP.Net

I have looked at

https://www.experts-exchange.com/questions/22583313/Open-PDF-file.html

and am still having problems. The table containing the links has three fields, ID, Volume, and Link. A Gridview is bound to the table and a hyperlink field has been created with the DataNavigateUrlField set to Link and the DataNavigateUrlFormatString set to {0}. (I think the problem is here, but don't know how to remedy it. The other things I have tried don't work, either.) This results in a 404 error indicating the link was not found, however the path was correct. So, I clearly don't understand how to do this. I have three reference books and none of them show this.
I would like instruction in the following:
1. How should the link field be filled, both for pdf files in wwwroot and files that are in a directory not in wwwroot. The test file is Test.pdf in  ~/Folder/Test.pdf where Folder is the folder containing Default.aspx. I have tried both  Folder/Test.pdf and Test.pdf with the same results.

2. What is the best way to archive .PDF files for anonymous users to be able to view and download, if desired?

3. How should the DataNavigateUrlFormatString be set based on the Link format in 2?

4. What is the best way to simply display a .PDF file using something like a link button? I got that to work once but lost the site and cannot reconstruct it. (I'm an old man just learning this so chalk it up to a senior moment.)

Thanks for your help.
Avatar of Bob Learned
Bob Learned
Flag of United States of America image

1) Hmmm, the "best" way is not always a single way.  It depends on factors like authorization, database types, personal preference, etc.  

2) SQL Server, MySQL, Oracle, etc., are good at storing files, and don't require much code to reconstruct.

3) DataNavigateUrlFormatString should be something like this:

       DataNavigateUrlFormatString="WebPage1.aspx?filename={0}"

4) I'm an old man, too, so I respect senior moments.

Bob
Avatar of rkulp

ASKER

Bob,

Thanks for your quick reply. I've been out of pocket for a few days and could not respond.

1 & 2) By this do you mean storing the whole pdf file as a field or simply storing the link to a location with the file? I have stored the link.
3) Well, I haven't been able to figure this one out. What is the proper control to pass the query string to? I have tried a detail view but that did not work. I have tried it without a control but that does not work. I overcame the senior moment and got a hyperlink to load the pdf but have not figured out how to have a hyperlink executed when the page loads. If I were loading a picture file, then I'd put the picture into an image field in a detail view. Not helpful for pdf files. In this case ignorance is not bliss.

Thanks a bunch.
Avatar of rkulp

ASKER

Bob,
I have made a very small amount of progress. At least I know how to pass the query string. At this point I have the hyperlink going to the path, but eventually I'll go to the ID and then get the path using another sqlDataSource on the display page. At least that is the plan now.

Here is my code, gleaned from several other sources, primarily a topic on p2p.wrox.com:

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim sLink As String = Server.MapPath("~/Newsletters/" & Request.QueryString("Link"))
        Dim fs As New System.IO.FileStream(sLink, IO.FileMode.Open, IO.FileAccess.Read)
        Dim Buffer(fs.Length) As Byte
        fs.Read(Buffer, 0, CInt(fs.Length))
        fs.Close()
        With Response
            .BufferOutput = True
            .ClearContent()
            .ClearHeaders()
            .AddHeader("Content-Length", Buffer.Length.ToString)
            .AddHeader("content-disposition", "inline")
            .ContentType = "application/pdf"
            .BinaryWrite(Buffer)
            .Flush()
            .Close()
        End With
    End Sub

I don't know if that works or not because the file cannot be found.  I have stepped through the subroutine in debug mode and sLink is the correct full path. Clearly, I'm missing something.
If you are having problems finding the file, then I wouldn't know how to help you, other than something like a rights issue.

Bob
Avatar of rkulp

ASKER

Bob,

I understand your inability to help on that. What I don't understand is that a straight hyperlink will open the file but the gridview hyperlink will not.  What is the difference between the two? Debug shows exactly the same path for the Response.WriteFile argument as the hyperlink argument. The error shows the complete physical path which is also correct. If it is a permission problem, both should fail.
Review:

1) Show me how you used the "straight" hyperlink

2) Show me how you tried to use the Gridview with a HyperlinkField

Bob
Avatar of rkulp

ASKER

Bob,

Thanks for your extrordinary support. Here is the code. DisplayNewsletter.aspx is linked to a masterpage but the content is empty.

Source for the page with the GridView and the hyperlink.

<%@ Page Language="vb" AutoEventWireup="false" MasterPageFile="~/MD12S.Master" CodeBehind="Default.aspx.vb" Inherits="lions12S._Default1" %>

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    <asp:SqlDataSource ID="newslettersDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:lions12SConnectionString %>"
        SelectCommand="SELECT * FROM [vw_aspnet_Newsletters]"></asp:SqlDataSource>
    <asp:GridView ID="GridView1" runat="server" AllowPaging="True" AllowSorting="True"
        AutoGenerateColumns="False" DataKeyNames="NewsletterID" DataSourceID="newsletersDataSource">
        <Columns>
            <asp:HyperLinkField DataNavigateUrlFields="Link" DataNavigateUrlFormatString="DisplayNewsletter.aspx?Link={0}"
                Text="View Newsletter" />
            <asp:BoundField DataField="Volume" HeaderText="Volume" SortExpression="Volume" />
            <asp:BoundField DataField="Link" HeaderText="Link" SortExpression="Link" />
            <asp:BoundField DataField="NewsletterID" HeaderText="NewsletterID" InsertVisible="False"
                ReadOnly="True" SortExpression="NewsletterID" />
        </Columns>
    </asp:GridView>
    <br />
    <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/Newsletters/Sept-Oct District Newsletter.pdf">HyperLink</asp:HyperLink>

</asp:Content>
*****************************************
Link field content:

Sept-Oct District Newsletter.pdf

**************************************************

CodeBehind for DisplayNewsletter.aspx:

Public Partial Class DisplayNewsletter
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim NewsletterPath As String = "~/Newsletters/" & Request.QueryString("Link")
        With Response
            .ClearContent()
            .ClearHeaders()
            .ContentType = "application/pdf"
            .WriteFile(NewsletterPath)
            .Flush()
            .Close()
        End With
    End Sub

End Class

****************************************

Source for DisplayNewsletter.aspx:

<%@ Page Language="vb" AutoEventWireup="false" MasterPageFile="~/MD12S.Master" CodeBehind="DisplayNewsletter.aspx.vb" Inherits="lions12S.DisplayNewsletter" %>

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    &nbsp;

</asp:Content>
ASKER CERTIFIED SOLUTION
Avatar of Bob Learned
Bob Learned
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of rkulp

ASKER

As shown in the link field content above, they are exactly the same. There is only one record in the table for testing. There are no blank or invalid values.
If you put a breakpoint on this line, can you verify what you are getting for 'NewsletterPath'?

Dim NewsletterPath As String = "~/Newsletters/" & Request.QueryString("Link")

Bob
Avatar of rkulp

ASKER

I have done that. It is exactly the same as the hyperlink:

~/Newsletters/Sep-Oct District Newsletter.pdf

Frustrating, or what?
Yes, it sounds as frustrating as some my problems that I have to solve.

Does this work?

<asp:HyperLinkField DataNavigateUrlFields="Link" DataNavigateUrlFormatString="~/Newsletters/{0}" Text="View Newsletter" />

Bob
Avatar of rkulp

ASKER

Bob,

With "~/Newsletters/{0}" one gets illegal characters in path error. Without the double quotes it cannot find the resource /Newsletters/Sep-Oct District Newsletter.pdf or it is not available.

My next try is to put the file outside the site and set the path directly to it in the hyperlink. If that works fine, then I'll change the path in the db and make the DataNavigateUrlFormatString={0}.
I'll let you know what happens.

Thanks.

Dick
What would happen if you encode the path?

Sep-Oct%20District%20Newsletter.pdf

Bob
Avatar of rkulp

ASKER

Bob,

It is the same as not encoding. Also, putting in the full path and using {0} makes it not be a hyperlink.
What about making it a template field and adding a hyperlink to that? Then the user would actually click a hyperlink. I have to work out the path part. That is the next thing I'll try.

Dick
Avatar of rkulp

ASKER

Bob,

Using the following "hard-wired" template field worked:

           <asp:TemplateField>
                <ItemTemplate><asp:HyperLink ID="hlLink" runat="server" NavigateUrl="~/Newsletters/Sept-Oct District Newsletter.pdf" Text = "View" />
                </ItemTemplate>
            </asp:TemplateField>

Replacing
NavigateUrl="~/Newsletters/Sep-Oct District Newsletter.pdf"
with
NavigateUrl="<%# Eval("Link")  %>"
where the path in Link is now the complete relative path as in the hard-wired version yields a correct path (i.e., it evaluates properly) but the resource is still not found or is temporily unavailable.
I got this idea from http://codeproject.wordpress.com/2007/10/13/83/ but trying it with the FormatUrl command Rana has in it yielded no response at all.

Dick
Eval("Link") is missing the ~/Newsletters part.

Try this:
   NavigateUrl="<%# '~/Newsletters' & Eval('Link')  %>"

Bob

Avatar of rkulp

ASKER

The link had ~/Newsletters/Sep-Oct District Newsletter.pdf in it. It yielded the Error 404 and showed the path as  /Newsletters/Sep-Oct District Newsletter.pdf. I created a Newsletters directory in C:\ and copied the pdf file there. That way the link worked from the GridView. That says the "~" has no effect on the path sent. My next try is to return the data to the original value (file name only) and then use your suggestion for the NavigateUrl.
All this is on a development computer. I don't know what will happen when it is moved to a host with the data tables on a SQLServer computer and the site on another one.

Dick
Does that mean that this might work?

<asp:HyperLinkField DataNavigateUrlFields="Link" DataNavigateUrlFormatString="{0}" Text="View Newsletter" />

Bob
Avatar of rkulp

ASKER

I stand corrected. The setup that worked actually had the link hard-coded. The "{0}" approach leads to an error that the path has illegal characters in it. I'll keep trying.

Dick
Avatar of rkulp

ASKER

Bob,

I want to thank you for your patience. It is finally working on another page but I don't know exactly why. In my searching I found a neat control for embedding a PDF in a web page at

http://www.codeproject.com/aspnet/EmbedPDFinWebpages.asp.

I'm going to close this and award the points.

Dick