Dynamic Folder Names with AjaxFileUpload

Ken Krugh 116 Reputation points
2024-07-18T17:04:20.35+00:00

I'm attempting to replace the upload /download pages of our very old ASP classic web site with a web forms app. Keeping as much of the back end stuff the same is important as there is code (mostly VBA in Word, Excel and Outlook) in our daily operation that uses the uploaded files.

I've managed to get things working with a login page that uses our existing database and redirects to the upload page that contains the AjaxFileUpload control.

My problem is that each client has a folder to which their files are uploaded and I can't find a way to dynamically change the folder in the AjaxFileUpload's _UploadComplete event. I've tried setting a session variable with the client ID on the login page, the value of which I can get in the Page_Load event of the upload page but is inaccessible in the AjaxFileUpload's code-behind event procedures _UploadComplete and _UploadCompleteAll. I've tried the same idea by setting an invisible label with the client ID in the Page_Load event, but again the label seems inaccessible in the AjaxFileUpload event procedures.

There are also other controls on the page I'll eventually need to access in this way after the upload, like the text box with the name of the person who uploaded. I suspect the inaccessibility of the session variables and label text from the AjaxFileUpload event procedures may be a security thing. Though being completely new to any web dev I very well could be missing something simple.

Thanks for any help,
Ken

.NET
.NET
Microsoft Technologies based on the .NET software framework.
3,625 questions
ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,411 questions
0 comments No comments
{count} votes

5 answers

Sort by: Most helpful
  1. Albert Kallal 5,231 Reputation points
    2024-07-18T20:10:33.41+00:00

    You can certainly use code to get/determine the logon, or use session() code in the 3 AjaxToolKit file uploader events.

    The only issue to keep in mind, since the upload is now ajax, then controls and values on the page of course cannot be used, since the web page is not being posted back to the server when those upload events are completed.

    So, nothing should prevent use of say session() in those events.

    I would suggest that you on the page load event (with the AJ fileuploader), you setup some session value in the page load event that sets the users folder in question.

    Hence, say some code like this on page load:

        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            If Not IsPostBack Then
                Session("UserName") = "Albert" ' testing
                Session("UpLoadFolder") = Server.MapPath("~/UpLoadFiles/Albert") ' testing
                LoadGrid()
                myfiles.Visible = False
                myupload.Visible = True
            End If
        End Sub
        Sub LoadGrid()
            GVFiles.DataSource = MyRst("SELECT * FROM MyFiles ORDER BY UpLoadDate")
            GVFiles.DataBind()
        End Sub
        Protected Sub AjaxFileUpload1_UploadComplete(sender As Object, e As AjaxControlToolkit.AjaxFileUploadEventArgs)
            ' save file to UpLoadFiles folder
            Dim strF As String = Session("UpLoadFolder") & e.FileName
            AjaxFileUpload1.SaveAs(strF)
            ' add this row to database.
            Using conn As New SqlConnection(My.Settings.TEST4)
                Using cmdSQL As New SqlCommand("INSERT INTO MyFiles 
                                               (UserName, FileName, SaveFilePath, UpLoadDate)
                                                VALUES (@User, @FileName, @FPath, @UpLoadDate)", conn)
                    cmdSQL.Parameters.Add("@User", SqlDbType.NVarChar).Value = Session("UserName")
                    cmdSQL.Parameters.Add("@FileName", SqlDbType.NVarChar).Value = e.FileName
                    cmdSQL.Parameters.Add("@FPath", SqlDbType.NVarChar).Value = strF
                    cmdSQL.Parameters.Add("@UpLoadDate", SqlDbType.DateTime).Value = DateTime.Now
                    conn.Open()
                    cmdSQL.ExecuteNonQuery()
                End Using
            End Using
        End Sub
    
    
    

    So, as above shows, use of session() is permitted in such upload events.

    The above thus results in this:

    uploadnew

    So, keep in mind that the ajaxfile upload events:

    They can NOT see nor use textboxes or controls on the page - the page does not have a post back, and thus you should consider the 3 server events as like a static method.

    The 3 events can use session, but the events can NOT use ViewState, since once again, that is client side browser side information - not available in the 3 events for the AjaxFileUpLoader.

    After all events are completed, the page is not posted back, and OFTEN I do want extra information such as user comments and other information entered by the user on that given page.

    Hence, I often add a final button on the page, hide the button, and have the "final" upload ALL event trigger this button, and thus the result is a final whole page post-back that occures AFTER all the files been upload. For example, in above after all files are done uploading, note how I switched my button/tab to show the uploaded files.

    This final code is triggered using JavaScript (jQuery in this example).

    hence this:

            <h4>Select Files to upload</h4>
            <br />
            <ajaxToolkit:AjaxFileUpload ID="AjaxFileUpload1" runat="server"
                OnUploadComplete="AjaxFileUpload1_UploadComplete"
                OnClientUploadCompleteAll="alldone" />
        </div>
    
        <asp:Button ID="cmdAllDone" runat="server" Text="Hidden all done upload Button"
            OnClick="cmdAllDone_Click" ClientIDMode="Static" Style="display: none" />
    
    
        <script>
    
            function alldone() {
    
                $('#cmdAllDone').click()
            }
    
        </script>
    
    
    

    So note how I added a client side JavaScript event to the AjaxFileUpLoad, and it runs the client side JavaScript routine called "alldone".

    And "all done" simply clicks the button I placed on the page. this results in a full page post back, and thus my code behind is free to do some final additional work, or in this case, toggle the div that shows all files uploaded.

    Hence the cmdAllDone_Click runs after all files are upload. This code:

        Protected Sub cmdAllDone_Click(sender As Object, e As EventArgs)
    
            myfiles.Visible = True
            myupload.Visible = False
    
            LoadGrid()  ' re-load re-fresh the GridView of files
            MyTabs.SelectedIndex = 1
    
        End Sub
    
    

    So, that final button click is really just a FYI as to how you can have some server side code run, and have a "often" needed post-back after all files been uploaded.

    However, the AJ FileUpLoad most certainly does allow use of session(). However, use of Viewstate(), or use of controls from the page are not available and can't be used.


  2. Lan Huang-MSFT 28,836 Reputation points Microsoft Vendor
    2024-07-19T02:21:11.08+00:00

    Hi @Ken Krugh,

    My problem is that each client has a folder to which their files are uploaded and I can't find a way to dynamically change the folder in the AjaxFileUpload's _UploadComplete event.

    You didn't provide your code, so we don't know why it doesn't work.

    Perhaps you can try the following method.

      protected void Page_Load(object sender, EventArgs e)
      {
          Session["path"] = @"C:\";
      }
      protected void AjaxFileUpload1_UploadComplete(object sender, AjaxControlToolkit.AjaxFileUploadEventArgs e)
      {
          var path = Session["path"] + e.FileName;
          AjaxFileUpload1.SaveAs(path);
          //  AjaxFileUpload1.SaveAs(@"C:\" + e.FileName + "");   
      }
    
     <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
     <ajaxToolkit:AjaxFileUpload ID="AjaxFileUpload1" runat="server" OnUploadComplete="AjaxFileUpload1_UploadComplete" />
    

    Best regards,
    Lan Huang


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread

    0 comments No comments

  3. Deleted

    This answer has been deleted due to a violation of our Code of Conduct. The answer was manually reported or identified through automated detection before action was taken. Please refer to our Code of Conduct for more information.


    Comments have been turned off. Learn more

  4. Deleted

    This answer has been deleted due to a violation of our Code of Conduct. The answer was manually reported or identified through automated detection before action was taken. Please refer to our Code of Conduct for more information.


    Comments have been turned off. Learn more

  5. Ken Krugh 116 Reputation points
    2024-07-19T19:24:32.3266667+00:00

    Something is happening that is SOMETIMES clearing the session variable, and I can't find it in my extreme noobness.

    The default.aspx is my login page, when the user successfully logs in the session variable ULFolder gets set based on the info from a database, then it redirects to the upload page. I know all of that works fine because in the Page_Load event of the upload page a label is being set with the ULFolder session variable, and it always fills in.

    ONLY SOMETIMES though when files are uploaded the ULFolder session variable is blank in the UploadComplete event.

    Thanks again for any help.

    The upload page. I've removed all the classic asp I mentioned earlier.

    <%@ Page Language="vb" AutoEventWireup="false" CodeBehind="TekntypeUpload.aspx.vb" Inherits="TekntypeUpDownLoad.TekntypeUpload" %>
    <%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>
    <!DOCTYPE html>
    <link href="TNTStyle.css" rel="stylesheet" type="text/css"/>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="FileUpDown" runat="server">
            <div>
                <asp:ScriptManager ID="ScriptManager1" runat="server" />
                File Upload<br />
                <ajaxToolkit:AjaxFileUpload ID="AjaxFileUpload1" runat="server" 
                    OnUploadComplete="AjaxFileUpload1_UploadComplete"
                    Width="50%" />
                <br />
                <asp:Label ID="LablULPath" runat="server" Visible="true" />
                <br />
                <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
            </div>
        </form>
    </body>
    </html>
    

    The Upload page code behind. Currently this is setting the path with a hard string and just using Debug.Print to show what the session variable is.

    Imports System
    Imports System.IO
    Imports System.Web
    Imports System.Web.UI.WebControls
    Imports AjaxControlToolkit
    
    Public Class TekntypeUpload
        Inherits System.Web.UI.Page
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            'These Response and HttpContext commands are to avoid caching.
            'When the Chrome option to "Continue where you left off" was turned on, and the browser was closed 
            '   while on this page, when it was opened again in would simply to the page. BOTH these commands 
            '   and setting the variable to false stopped that.
            'Response.Cache.SetCacheability(HttpCacheability.NoCache)
            'Response.Cache.SetNoStore()
            'Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches)
            'Response.Expires = -1
            'Response.AppendHeader("Pragma", "no-cache")     'HTTP 1.0
            'HttpContext.Current.Response.Cache.SetAllowResponseInBrowserHistory(False)
            'HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache)
            'HttpContext.Current.Response.Cache.SetNoStore()
            'Response.Cache.SetExpires(DateTime.Now)
            'Response.Cache.SetValidUntilExpires(True)
    
            If Session("IsULLoggedIn") Is Nothing OrElse Session("IsULLoggedIn") = False Then
                Session("ShowLoginMsg") = "UPLOAD"
                Response.Redirect("default.aspx", True)
            Else
                'MsgBox(Session("ShowLoginMsg") Is Nothing)
            End If
            Session("ShowLoginMsg") = ""
            Session("IsULLoggedIn") = False     'Used by the upload page to determine whether they logged in.
    
            Me.LablULPath.Text = "Page_Load: " & Session("ULFolder")
        End Sub
    
        Protected Sub AjaxFileUpload1_UploadComplete(sender As Object, e As AjaxControlToolkit.AjaxFileUploadEventArgs) Handles AjaxFileUpload1.UploadComplete
            Dim ULPath As String = "\\Tntweb3\ftp_users\Upload\TNT"
    
            Debug.Print("UploadStart Session(""ULFolder""): " & Session("ULFolder"))
    
            'If Not System.IO.Directory.Exists(Session("ULFolder")) Then
            '    System.IO.Directory.CreateDirectory(Session("ULFolder"))
            'End If
    
            'AjaxFileUpload1.SaveAs(Session("ULFolder") & "\" & e.FileName)
            AjaxFileUpload1.SaveAs(ULPath & "\" & e.FileName)
        End Sub
    End Class
    

    web.config:

    <?xml version="1.0"?>
    <configuration>
    	<configSections>
    	</configSections>
    	<appSettings/>
    	<connectionStrings>
      <add name="TekntypeUpDownLoad.My.MySettings.AccessODBC" connectionString="DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=\\tntweb3\FTP_USERS\webs\tekntype\base\drowssap - Copy.mdb"
       providerName="System.Data.Odbc" />
     </connectionStrings>
    	<!--
        For a description of web.config changes see http://go.microsoft.com/fwlink/?LinkId=235367.
        The following attributes can be set on the <httpRuntime> tag.
          <system.Web>
            <httpRuntime targetFramework="4.5.2" />
          </system.Web>
      -->
    	<system.web>
    		<!--Time and file size override. executionTimeout is seconds, maxRequestLength is kilobytes.-->
    		<httpRuntime executionTimeout="1800" maxRequestLength="1024000"/>
    		<!--Start manually added for Ajax fileupload.-->
    		<httpHandlers>
    			<add verb="*" 
    				  path="AjaxFileUploadHandler.axd" 
    				  type="AjaxControlToolkit.AjaxFileUploadHandler, AjaxControlToolkit" />
    		</httpHandlers>
    		<!--End manually added for Ajax fileupload.-->
    		<!-- 
             Visual Basic options:
             Set strict="true" to disallow all data type conversions 
             where data loss can occur. 
             Set explicit="true" to force declaration of all variables.
          -->
    		<compilation debug="true" strict="false" explicit="true" targetFramework="4.5.2">
    			<assemblies>
    				<add assembly="System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
    				<add assembly="System.Web.Extensions.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    			</assemblies>
    		</compilation>
    		<!--
          The <authentication> section enables configuration 
          of the security authentication mode used by 
          ASP.NET to identify an incoming user. 
        -->
    		<!--
           The <customErrors> section enables configuration 
           of what to do if/when an unhandled error occurs 
           during the execution of a request. Specifically, 
           it enables developers to configure html error pages 
           to be displayed in place of a error stack trace.
           <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
             <error statusCode="403" redirect="NoAccess.htm" />
             <error statusCode="404" redirect="FileNotFound.htm" />
           </customErrors>
        -->
    		<customErrors mode="Off"/>
    		<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
    			<namespaces>
    				<clear/>
    				<add namespace="System"/>
    				<add namespace="System.Collections"/>
    				<add namespace="System.Collections.Generic"/>
    				<add namespace="System.Collections.Specialized"/>
    				<add namespace="System.Configuration"/>
    				<add namespace="System.Text"/>
    				<add namespace="System.Text.RegularExpressions"/>
    				<add namespace="System.Linq"/>
    				<add namespace="System.Xml.Linq"/>
    				<add namespace="System.Web"/>
    				<add namespace="System.Web.Caching"/>
    				<add namespace="System.Web.SessionState"/>
    				<add namespace="System.Web.Security"/>
    				<add namespace="System.Web.Profile"/>
    				<add namespace="System.Web.UI"/>
    				<add namespace="System.Web.UI.WebControls"/>
    				<add namespace="System.Web.UI.WebControls.WebParts"/>
    				<add namespace="System.Web.UI.HtmlControls"/>
    			</namespaces>
    		</pages>
    	</system.web>
    	<!-- 
            The system.webServer section is required for running ASP.NET AJAX under Internet
            Information Services 7.0.  It is not necessary for previous version of IIS.
        -->
    	<system.webServer>
    		<!--Start manually added for Ajax fileupload.-->
    		<validation validateIntegratedModeConfiguration="false"/>
    		<handlers>
    			<add name="AjaxFileUploadHandler"
    				  verb="*" 
    				  path="AjaxFileUploadHandler.axd"
    				  type="AjaxControlToolkit.AjaxFileUploadHandler, AjaxControlToolkit" />
    		</handlers>
    		<!--End manually added for Ajax fileupload.-->
    		<httpErrors errorMode="Detailed" />
    		<security>
    			<requestFiltering>
    				<!--File size and override for IIS7 and above. Measurement is bytes.-->
    				<requestLimits maxAllowedContentLength="3000000000"/>
    			</requestFiltering>
    		</security>
    	</system.webServer>
    </configuration>