ASP .NET 2.0 Application Page not working from Subfolder

Posted on 2011-04-19
Last Modified: 2012-08-13

I've developed a nice VB supported website using a site.master that I am developing some content management system functions (e.g., uploading images to image folder, documents to document folder, editing web pages).  All of my functions work when they are stored in the main website folder (i.e., /main/). I've also modified the web.config so that the pages are only available to authenticated users. I have also set up restrictions so that the editor pages can not be edited using the editing tools.  All of this editing will happen on a staging server (as manual edits are completed now), then will be copied over by another person to the live (public) server.

Since the person moving the files live, is not the same person doing the development, I would like to keep all of the editing files in one folder (e.g., /main/cms/) that will not be copied to the live server.   When I put my files into the /cms/ folder, I run into errors. More specifically, the files will read from other directories (e.g., /main/images), but when I try to upload or delete a file, I get the custom error page I developed and am re-directed to the default page.  

When I look at the the error line in the URL from the error page re-direct, it appears that the file is trying to submit from the main folder location. For example, when trying to delete an image using my images.aspx file in cms (i.e., /main/cms/images.aspx), it appears as if the "action" does not account for the "cms."

I've added the site.master to the cms folder and referenced correctly, with the same result.  I am wondering if I need to somehow re-write the action statement or how to resolve this issue.  I tried to add a C# script in the app_folder as my latest resort, but haven't had any luck referencing it correctly in the page.  I'm not even sure that that is the correct solution and I am stuck.
Question by:atljarman
    LVL 3

    Expert Comment

    Could you post any code you use to save the files in it's directories?

    Author Comment

    I meant to upload one of the files previously.  In this attachment, I've uploaded the two files.  The first one displays the contents of the document folder.  If the user clicks on the document name, it displays the document.  If the user clicks on delete, it will delete when the file is in the main folder but not in the cms (i.e., sub folder).  The second, is the file to upload documents to the document folder.  Again, this will work from the main folder, but not from the sub folder.
    'This is the page code to view documents in the document folder.
    <%@ Page Language='VB' MasterPageFile='site.master' Title='Content Page for documents.aspx' %>
    <%@ Import Namespace="System.IO" %>
    <script runat='server'>
      Sub Page_Load(sender as Object, e as EventArgs)
        If Not Page.IsPostBack then
    	Dim dirInfo As New DirectoryInfo(Server.MapPath("~\documents\"))
    '      Dim dirInfo as New DirectoryInfo(Server.MapPath("."))
    'articleList.DataSource = dirInfo.GetFiles("*.aspx")
            articleList.DataSource = dirInfo.GetFiles("*.*")
        End If
      End Sub
       Sub articleList_ItemDataBound(ByVal sender As Object, ByVal e As DataGridItemEventArgs)
        ' First, make sure we're NOT dealing with a Header or Footer row
         If e.Item.ItemType <> ListItemType.Header And _
            e.Item.ItemType <> ListItemType.Footer Then
            'Now, reference the Button control that the Delete ButtonColumn 
            'has been rendered to
             Dim deleteButton As Button = e.Item.Cells(0).Controls(0)
             'We can now add the onclick event handler
             deleteButton.Attributes("onclick") = "javascript:return " & _
             "confirm('Are you sure you want to delete the file " & _
             DataBinder.Eval(e.Item.DataItem, "Name") & "?')"
         End If
       End Sub
      Sub articleList_DeleteFile(ByVal sender As Object, ByVal e As DataGridCommandEventArgs)
         'First, get the filename to delete
          Dim fileName As String = articleList.DataKeys(e.Item.ItemIndex)
          lblMessage.Text = "You opted to delete the file " & fileName & ".<br /><br />"
          'You would want to rebind the Directory's files to the DataGrid after
          'deleting the file...
           Dim dirInfo As New DirectoryInfo(Server.MapPath("~\documents\"))
              articleList.DataSource = dirInfo.GetFiles("*.*")
         End Sub
    <asp:Content ID='Content1' ContentPlaceHolderID='Main' Runat='Server'>
    <br />
    <h2>Upload Documents</h2>
    	<p><a href="~\_documents.aspx" runat="server">Click here to Upload Documents</a>.</p>
    <h2>View Delete Doucments</h2>
    <p>Below is a list of files in the main directory.  If you choose to delete a file, this can not be undone.</p>
     <asp:label runat="server" id="lblMessage" Font-Italic="True" ForeColor="Red" />
      <asp:DataGrid runat="server" id="articleList" Font-Name="Verdana"
          AutoGenerateColumns="False" AlternatingItemStyle-BackColor="#eeeeee"
          HeaderStyle-BackColor="Navy" HeaderStyle-ForeColor="White"
          HeaderStyle-Font-Size="10.5pt" HeaderStyle-Font-Bold="True"
          <asp:ButtonColumn Text="Delete" ButtonType="PushButton" 
                  CommandName="Delete" />
          <asp:HyperLinkColumn DataNavigateUrlField="Name" DataNavigateUrlFormatString="documents\{0}"
                  DataTextField="Name" HeaderText="File Name" />
          <asp:BoundColumn DataField="LastWriteTime" 
                  HeaderText="Last Write Time"
                  DataFormatString="{0:d}" />
          <asp:BoundColumn DataField="Length" HeaderText="File Size"
    	  	      DataFormatString="{0:#,### bytes}" />
    'This is the file to upload documents to the documents folder.  The validation isn't correct, as it send validation to the client even when the file types are correct.
    <%@ Page Language='VB' MasterPageFile='usphssite.master' Title='Content Page for documents.aspx' %>
    <script runat='server'>
    Protected Sub Button1_Click(ByVal sender As Object, _
       ByVal e As System.EventArgs)
            'Dim filepath As String = "C:\corpslinks\Veterinarian\documents"
            'Dim filepath As String = Server.MapPath("~\documents\")
            Dim filepath As String = Server.MapPath("~\documents")
       Dim uploadedFiles As HttpFileCollection = Request.Files
       Dim i As Integer = 0
       Do Until i = uploadedFiles.Count
         Dim userPostedFile As HttpPostedFile = uploadedFiles(i)
            If (userPostedFile.ContentLength > 0) Then
               Label1.Text += "<u>File #" & (i + 1) & "</u><br>"
               Label1.Text += "File Content Type: " & _
                  userPostedFile.ContentType & "<br>"
               Label1.Text += "File Size: " & _
                  userPostedFile.ContentLength & "kb<br>"
               Label1.Text += "File Name: " & _
                  userPostedFile.FileName & "<br>"
               userPostedFile.SaveAs(filepath & "\" & _
               Label1.Text += "Location where saved: " & _
                  filepath & "\" & _
                  System.IO.Path.GetFileName(userPostedFile.FileName) & _
            End If
         Catch ex As Exception
            Label1.Text += "Error:<br>" & ex.Message
         End Try
         i += 1
    End Sub
    <asp:Content ID='Content1' ContentPlaceHolderID='Main' Runat='Server'>
    <p>This page is used to upload documents to the documents folder.  These will be available to reference from your page once uploaded.</p>
    	<p><a href="_documentlist.aspx" runat="server">Return to the document list</a>.</p>
    <h2>Upload Doucments</h2>
    <asp:FileUpload ID="FileUpload1" runat="server" /><br />
    <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="FileUpload1"
            Display="Dynamic" ErrorMessage="Please specify an image file." SetFocusOnError="True"
        <asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server" ControlToValidate="FileUpload1"
    ErrorMessage="Upload .pdf, .doc, .ppt, and .xls files only." SetFocusOnError="True" 
            Display="Dynamic" ValidationGroup="Group1"></asp:RegularExpressionValidator><br />
    <asp:FileUpload ID="FileUpload2" runat="server" /><br />
    id="RegularExpressionValidator2" runat="server" 
    ErrorMessage="Upload .pdf, .doc, .ppt, and .xls files only." 
    Display="Dynamic" ValidationGroup="Group1">
    <br />
    <asp:FileUpload ID="FileUpload3" runat="server" /><br />
    id="RegularExpressionValidator3" runat="server" 
    ErrorMessage="Upload .pdf, .doc, .ppt, and .xls files only." 
    Display="Dynamic" ValidationGroup="Group1">
    <br />
    <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" 
     Text="Upload File(s)" ValidationGroup="Group1"/>&nbsp;<br />
    <br />
    <asp:Label ID="Label1" runat="server"></asp:Label><br /><br />
    <asp:Label ID="Label2" runat="server"></asp:Label><br /><br />
    <asp:Label ID="Label3" runat="server"></asp:Label><br /><br />
    <br />

    Open in new window


    Accepted Solution

    Here is how to solve this:

    Add the following --> actionscript.vb to the App_Folder (code attached)

    Reference the class in the top of you page as such: <%@ Import Namespace="testaction" %>

    In your script, use this code to replace the action to the correct folder.  

            Me.Response.Filter = New cdsnetFormActionModifier(Me.Response.Filter, "cms\_advfileeditor.aspx")

    The example here is the _advfileeditor.aspx in the cms in relation to the site.master that is at the root or base folder.
    'actionscript.vb to the App_Folder
    Imports System.Data
    Imports System.Configuration
    Imports System.Web
    Imports System.Web.Security
    Imports System.Web.UI
    Imports System.Web.UI.WebControls
    Imports System.Web.UI.WebControls.WebParts
    Imports System.Web.UI.HtmlControls
    Imports System.IO
    Imports System.Text.RegularExpressions
    Namespace testaction
    	Public Class cdsnetFormActionModifier
    		Inherits Stream
    		Private _sink As Stream
    		Private _position As Long
    		Private _url As String
    		Public Sub New(sink As Stream, url As String)
    			_sink = sink
    			_url = "$1" & url & "$3"
    		End Sub
    		Public Overrides ReadOnly Property CanRead() As Boolean
    				Return True
    			End Get
    		End Property
    		Public Overrides ReadOnly Property CanSeek() As Boolean
    				Return True
    			End Get
    		End Property
    		Public Overrides ReadOnly Property CanWrite() As Boolean
    				Return True
    			End Get
    		End Property
    		Public Overrides ReadOnly Property Length() As Long
    				Return 0
    			End Get
    		End Property
    		Public Overrides Property Position() As Long
    				Return _position
    			End Get
    				_position = value
    			End Set
    		End Property
    		Public Overrides Function Seek(offset As Long, direction As System.IO.SeekOrigin) As Long
    			Return _sink.Seek(offset, direction)
    		End Function
    		Public Overrides Sub SetLength(length As Long)
    		End Sub
    		Public Overrides Sub Close()
    		End Sub
    		Public Overrides Sub Flush()
    		End Sub
    		Public Overrides Function Read(buffer As Byte(), offset As Integer, count As Integer) As Integer
    			Return _sink.Read(buffer, offset, count)
    		End Function
    		Public Overrides Sub Write(buffer As Byte(), offset As Integer, count As Integer)
    			Dim s As String = System.Text.UTF8Encoding.UTF8.GetString(buffer, offset, count)
    			Dim reg As New Regex("(<form.*action="")([^""]*)" & "(""[^>]*>)", RegexOptions.IgnoreCase)
    			Dim m As Match = reg.Match(s)
    			If m.Success Then
    				Dim form As String = reg.Replace(m.Value, _url)
    				Dim iform As Integer = m.Index
    				Dim lform As Integer = m.Length
    				s = s.Substring(0, iform) & form & s.Substring(iform + lform)
    			End If
    			Dim yaz As Byte() = System.Text.UTF8Encoding.UTF8.GetBytes(s)
    			_sink.Write(yaz, 0, yaz.Length)
    		End Sub
    	End Class
    End Namespace

    Open in new window


    Author Closing Comment

    I found the solution as C# on another site and converted it to VB.  This is functioning for my site.

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    Looking for New Ways to Advertise?

    Engage with tech pros in our community with native advertising, as a Vendor Expert, and more.

    I recently went through the process of creating a Calendar Control of events with the basis of using a database to keep track of the dates that are selectable, one requirement was to have the selected date pop-up in a simple lightbox.  At first this…
    Problem Hi all,    While many today have fast Internet connection, there are many still who do not, or are connecting through devices with a slower connect, so light web pages and fast load times are still popular.    If your ASP.NET page …
    Migrating to Microsoft Office 365 is becoming increasingly popular for organizations both large and small. If you have made the leap to Microsoft’s cloud platform, you know that you will need to create a corporate email signature for your Office 365…
    This video discusses moving either the default database or any database to a new volume.

    759 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    10 Experts available now in Live!

    Get 1:1 Help Now