CustomStateStoreProvider - not showing progress bar update

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

CustomStateStoreProvider - not showing progress bar update

Guest-962

Hi Dean,

When using the built-in AdaptiveUploadStateStoreProvider , the progress bar works fine. However since our production servers are on a webfarm where session is not shared, I created a custom StateStoreProvider as per the documentation. The web.config has then been updated to use the new custom State Store Provider. The code (load function, Merge and Save etc) in the new CustomStateStoreProvider is executing with the correct KeyID as can be seen if written out to a log file.

 

However the progress bar does not get refreshed., though the file gets uploaded fine.

 

These are the steps I followed.

 

1)  Referenced the CompanySpecific dll ( that obtains the object used to save our application session information) from the Brettle.Web.NeatUpload project.

 

2)  Added a new class MyCompanyUploadStateStoreProvider.cs

 

3)  Compiled to create a new version of the Brettle.Web.NeatUpload.dll which is being used by our application.

 

4)  Made web.config changes to reference this new StateStoreProvider.

 

 

If I change the web.config to revert back to the default StateStoreProvider the progress bar works fine.

 

 

Can you help?

CustomStateStoreProvider - code

using System;

 

using System.Collections.Specialized;

 

using System.Web;

 

using System.IO;

 

using System.Runtime.Serialization;

 

using System.Runtime.Serialization.Formatters.Binary;

 

using Brettle.Web.NeatUpload.Internal.Module;

 

 

namespace Brettle.Web.NeatUpload

 

{

 

    //-------------------------------------------------------------------------------------------

 

    /// <summary>

 

    /// This will store the Neatupload variables in the Axentis State Variable.

 

    /// Needed for updating  progress bar when used on a webfarm.   

 

    /// </summary>

 

    /// <remarks>

 

    /// This class is instantiated by NeatUpload if it is added in the providers; section of

 

    /// the neatUpload section.  Application developers should not instantiate it directly.

 

    /// </remarks>

 

    public class MyCompanyUploadStoreProvider : UploadStateStoreProvider

 

    {

 

        public override string Description { get { return "Stores UploadState objects

 

            in the MyCompanyStateStoreObj of the current process."; } }

 

        private static string KeyPrefix = "NeatUpload_MyCompanyUpload_";

 

        private string _name = null;

 

        //public override void Initialize(string name,  

 

        //      System.Collections.Specialized.NameValueCollection attrs)

 

        //{

 

        //    _name = name;

 

        //}

 

        //---------------------------------------------------------------------------------------

 

        /// <summary>

 

        /// Returns an  UploadState for a given post-back ID. 

 

        /// </summary>

 

        /// <param name="postBackID">

 

        /// A post-back ID identifying the UploadState

 

        /// </param>

 

        /// <returns>

 

        /// The UploadState corresponding to

 

        /// <paramref name="postBackID"/>, or null if none exists.

 

        /// </returns>

 

        ///

 

        public override UploadState Load(string postBackID)

 

        {

 

            string key = KeyPrefix + postBackID;

 

            UploadState otempUploadState = null;

 

            //Convert state variable from string to memorystream.

 

            MyCompanyStateStoreObj oMyCompanyState = new MyCompanyStateStoreObj ();

 

            if (HttpContext.Current.Request.Cookies.Get("Session") != null)

 

            {

 

                string sSessionID = "";

 

                string sUPloadState = "";

 

                sSessionID = System.Web.HttpContext.Current.Request.Cookies.Get("Session").Value;

 

                oMyCompanyState.Load(sSessionID);

 

                if (oMyCompanyState.GetValue(key) != null)

 

                {

 

                    sUPloadState = oMyCompanyState.GetValue(key).ToString();

 

                    //StreamWriter sw = File.AppendText(@"C:\log.txt");

 

                    //sw.WriteLine("MyCompanyUploadStoreProvider:LOAD : key=" + key);

 

                    //sw.Close();

 

                    if (sUPloadState != "")

 

                    {

 

                        byte[] byteUploadState = Convert.FromBase64String(sUPloadState);

 

                        MemoryStream msUploadState = new MemoryStream(byteUploadState);

 

                        IFormatter formatter = new BinaryFormatter();

 

                        using (msUploadState)

 

                        {

 

                            msUploadState.Position = 0;

 

                            otempUploadState = (UploadState)formatter.Deserialize(msUploadState);

 

                        }

 

                    }

 

                }

 

                else

 

                {

 

                    otempUploadState = null;

 

                }

 

            }

 

            else

 

            {

 

                otempUploadState = null;

 

            }

 

            oMyCompanyState = null;

 

            return otempUploadState;

 

        }

 

        //---------------------------------------------------------------------------------------

 

        /// Merges a particular <see cref="UploadState"/> with the stored <see

 

        /// cref="UploadState"/> and store

 

        /// the merged <see cref="UploadState"/>.

 

        /// </summary>

 

        /// <param name="uploadState">

 

        /// The <see cref="UploadState"/> to be merged.

 

        /// </param>

 

        /// <remarks>When this method returns, <paramref name="uploadState"/> and the

 

        /// stored <see cref="UploadState"/>

 

        /// will be equivalent (though not necessarily identical) and either may have changed

 

        /// as a result

 

        /// of the merge.</remarks>

 

        public override void MergeAndSave(UploadState uploadState)

 

        {

 

            string sSerializedUploadState = "";

 

            string sSessionID = "";

 

            string key = KeyPrefix + uploadState.PostBackID;

 

          

 

            try

 

            {

 

              

 

                UploadState storedUploadState = Load(uploadState.PostBackID);

 

                Merge(uploadState, storedUploadState);

 

                string sUploadState = "";

 

                IFormatter formatter = new BinaryFormatter();

 

                using (System.IO.MemoryStream output = new System.IO.MemoryStream())

 

                {

 

                    //Save New File contents

 

                    formatter.Serialize(output, uploadState);

 

                    sUploadState = GetStringFromMemoryStream(output);

 

                }

 

               //Convert memorystream to string and store it in state variable.

 

                MyCompanyStateStoreObj oMyCompanyState = new MyCompanyStateStoreObj ();

 

                if (System.Web.HttpContext.Current.Request.Cookies.Get("Session") != null)

 

                {

 

                     sSessionID =

 

                     System.Web.HttpContext.Current.Request.Cookies.Get("Session").Value;

 

                     oMyCompanyState.Load(sSessionID);

 

                     oMyCompanyState.SetValue(key, sUploadState);

 

                     oMyCompanyState.Save();

 

                     //StreamWriter sw = File.AppendText(@"C:\log.txt");

 

                     //sw.WriteLine("MyCompanyUploadStoreProvider:MERGE AND SAVE : key=" + key);

 

                     //sw.Close();

 

                }

 

            }

 

            catch (Exception exBrettle)

 

            {

 

               

 

            }

 

        }

 

        //---------------------------------------------------------------------------------------

 

        /// <summary>

 

        /// Responsible for converting memory stream to string.

 

        /// </summary>

 

        /// <param name="memUploadState">

 

        /// The memory stream which is to be converted to string

 

        /// </param>

 

 

        public static string GetStringFromMemoryStream(MemoryStream memUploadState)

 

        {

 

            byte[] byteArrUploadState = memUploadState.ToArray();

 

            string sUploadState = Convert.ToBase64String(byteArrUploadState);

 

            return sUploadState;

 

        }

 

        //---------------------------------------------------------------------------------------

 

        /// <summary>

 

        /// Responsible for deleting the <see cref="UploadState"/> for a post-back ID

 

        /// from storage.

 

        /// </summary>

 

        /// <param name="postBackID">

 

        /// The post-back ID to be deleted.

 

        /// </param>

 

        /// <remarks>Subclasses should override this method to avoid leaking <see

 

        /// cref="UploadState"/>

 

        /// objects.</remarks>

 

        protected override void Delete(string postBackID)

 

        {

 

            string key = KeyPrefix + postBackID;

 

            //Delete the state value

 

            MyCompanyStateStoreObj oMyCompanyState = new MyCompanyStateStoreObj ();

 

            if (System.Web.HttpContext.Current.Request.Cookies.Get("Session") != null)

 

            {

 

                string sSessionID =

 

                    System.Web.HttpContext.Current.Request.Cookies.Get("Session").Value;

 

                oMyCompanyState.Load(sSessionID);

 

                oMyCompanyState.SetValue(key, null);

 

                oMyCompanyState.Save();

 

            }

 

            oMyCompanyState = null;

 

        }

 

        //---------------------------------------------------------------------------------------

 

        /// <summary>

 

        /// Returns the <see cref="UploadStateStoreProvider.CleanUpIfStaleCallback"/> that

 

        /// NeatUpload should call when a post-back ID

 

        /// might be stale.

 

        /// </summary>

 

        /// <returns>

 

        /// The <see cref="UploadStateStoreProvider.CleanUpIfStaleCallback"/>.

 

        /// </returns>

 

        public override CleanUpIfStaleCallback GetCleanUpIfStaleCallback()

 

        {

 

            Cleaner cleaner = new Cleaner(this);

 

            return cleaner.CleanUpIfStale;

 

        }

 

        [ThreadStatic]

 

        private static HttpApplicationState ThreadStaticApplication;

 

        private class Cleaner

 

        {

 

            internal Cleaner(MyCompanyUploadStoreProvider provider)

 

            {

 

                Provider = provider;

 

                //Application = HttpContext.Current.Application;

 

            }

 

 

            internal void CleanUpIfStale(string postBackID)

 

            {

 

                //MyCompanyUploadStoreProvider.ThreadStaticApplication = Application;

 

                //Provider.CleanUpIfStale(postBackID);

 

                try

 

                {

 

                    UploadState uploadState = Provider.Load(postBackID);

 

                    if (uploadState != null && uploadState.TimeOfLastMerge.AddSeconds( Config.Current.StateStaleAfterSeconds) < DateTime.Now)

 

                    {

 

                        foreach (UploadedFile f in uploadState.Files)

 

                            f.Dispose();

 

                        Provider.Delete(postBackID);

 

                    }

 

                }

 

                catch (Exception ex)

 

                {

 

                   

 

                }

 

            }

 

            MyCompanyUploadStoreProvider Provider;

 

        }

 

    }

 

}

 

 

 

Reply | Threaded
Open this post in threaded view
|

Re: CustomStateStoreProvider - not showing progress bar update

Dean Brettle
Administrator
My best guess is that calling oMyCompanyState.Save() might not actually cause the state to be shared immediately.  If the state isn't shared until the end of the current request, that would explain the behavior you are seeing.  It would normally be reasonable behavior for sharing session data across servers because you aren't normally dealing with concurrent requests accessing the same session like NeatUpload does.

If you log uploadState.BytesRead in Load() (after deserialization) and MergeAndSave() (after merge, but before serialization), what do you see?  If it looks like the deserialized doesn't match the serialized value, that would be consistent with my hypothesis.  You could even eliminate serialization as the issue by just storing uploadState.BytesRead under a separate key in your
oMyCompanyState and using logging to see whether it is available during a subsequent Load() call.

If you can't figure it out, send your log files and corresponding code to me (dean at brettle dot com).

--Dean

Reply | Threaded
Open this post in threaded view
|

Re: CustomStateStoreProvider - not showing progress bar update

Guest-962
Thanks Dean,  I will try this out and post an update
Reply | Threaded
Open this post in threaded view
|

Re: CustomStateStoreProvider - not showing progress bar update

Guest-962

Hi Dean,

I had missed out specifying the  defaultStateStoreProvider attribute in the <neatUpload > element's definiton , even though I had specified that in each of the individual pages defined in the <location> values.

<neatUpload useHttpModule="false" maxNormalRequestLength="20384" maxRequestLength="2097151" decryptionKey="003401f7012b019021b4025802bc0720" defaultStateStoreProvider="MyCompanyUploadStoreProvider" >

It is working now.

Thanks

Reply | Threaded
Open this post in threaded view
|

Re: CustomStateStoreProvider - not showing progress bar update

Dean Brettle
Administrator
Ah...  The key was probably that it wasn't being used for the NeatUpload/MultiRequestUploadHandler.ashx page.  That page is what handles flash-based MultiFile uploads.

--Dean