2

I'm sure I'm treading in the steps of many before but can't seem to solve this one issue. The goal is to create a file upload page for an ASP.NET 2.0 site that has a realtime progress bar (for potentially multiple files).

I've already implemented and tested most parts of the solution. But stupidly, I can't seem to get it to all work together.

  1. Built a custom HttpModule that handles PreRequestHandlerExecute event (originally used BeginRequest--but I wanted access to Session) for the relevant requests and parses the incoming form post data in chunks using HttpWorkerRequest object. Realtime progress is saved to Session.

  2. Built web service in the same application that offers ScriptMethod returning JSON to a jQuery request with progress information it extracts from the Session. Tested this and it works.

My issue is I haven't been able to have the jQuery polling of the ScriptMethod in (2) occur while (1) is in process. The jQuery calls just seem to queue up somewhere and as soon as the upload has fully posted, they all return suddenly with "100%". So the async part isn't working.

Things I have tried:

  • Submitting the file upload post with .ajaxForm() (the jQuery Forms plugin).
  • Various scenarios of nesting using IFRAMEs.
  • Having a separate page (in separate browser tab) run the polling jQuery while I submit my uploads from the first page. The polls still halt and queue up until after the first page completes.

I've seen other very similar solutions online that others claim worked for them, so it must be possible, and I'm just missing something basic.

UPDATE:

Problem has been solved and all is now working. Please see my own answer below regarding SessionState locking.

Special Sauce
  • 5,338
  • 2
  • 27
  • 31
  • 1
    Is your web page HTML5 based? Realtime progress is not possible without it. (Previously pages used things like Flash for this) – Billy ONeal Dec 18 '12 at 01:54
  • The web page is not HTML5 based. Are you sure realtime progress is impossible without HTML5 or Flash? Here are two solutions the supposedly work and have very high ratings: http://www.codeproject.com/Articles/113418/ASP-NET-File-Upload-with-Progress-Bar and http://www.codeproject.com/Articles/14832/ASP-NET-file-post-direct-to-disk-with-upload-file – Special Sauce Dec 18 '12 at 02:04
  • Interesting. It looks like they're using an `iframe` as a hack to allow the submission of the form in the background. The form with the file itself is in that separate `iframe`. – Billy ONeal Dec 18 '12 at 02:09
  • Also note that several of the comments in that article say "this is not upload progress" -- your handler in ASP land doesn't run until after the file is fully uploaded. So I return to my original statement and say that you need a browser plugin or HTML 5 for this. – Billy ONeal Dec 18 '12 at 02:12
  • The comments you noted gave me a scare, but thankfully my own testing proved them to be untrue. If you handle BeginRequest or PreRequestHandlerExecute on your own HttpModule, you do get access to the incoming form post stream almost immediately (you do have to wait for the first 50KB or so which it sticks in a so-called "preloaded buffer"). But after that you can monitor the stream realtime as it receives from the client. – Special Sauce Dec 18 '12 at 04:28

2 Answers2

0

I finally stumbled across the cause: ASP.NET SessionState locking.

The problem was elegantly posed and answered on this SO post: ASP.net session request queuing

This aspect is not mentioned in any of the online material pertaining to ASP.NET file upload realtime progress and at least one of the solutions I mentioned in the initial comments above failed to explicitly set EnableSessionState="false" in their upload page's directive—likely leading to some of the complaints on its usage. (Note that you can also set to Readonly for reader-writer locking benefits).

In short, once you instantiate any Session object for a user, all future concurrent page requests for that user will block by default because EnableSessionState is True by default. I'm honestly surprised I've never run into this issue earlier in my career. Anyway I hope it helps someone else out. And for the record, I do have realtime progress bar now working just fine in ASP.NET 2.0 without using Flash or HTML5—status is now being tracked through Application state.

Community
  • 1
  • 1
Special Sauce
  • 5,338
  • 2
  • 27
  • 31
0

I will also make some very brief comments on the 2 links I referenced above to help keep anyone else from being waylaid by some serious issues in those codebases:

  • ASP.NET File Upload with Progress Bar by Sunasara Imdadhusen: This example looks pretty but is virtually useless as it only tracks the progress of writing the file to the disk AFTER the file upload has already fully completed (usually the longer part for large files).

  • ASP.NET file post direct to disk with upload file progress support by Travis Whidden: A far better starting point, as this code does implement custom HttpModule to monitor upload in realtime. However, the buffer processing class FileProcessor.cs has a variety of bugs and should be rewritten. Also it is safest to extract form post boundary string from the headers themselves per HTTP spec.

Lastly, for those on .NET 4.0 and MVC 3+, the equivalent solution is far simpler due to the new Request.GetBufferlessInputStream() method—see this article for details: http://vanacosmin.ro/Articles/Read/AjaxFileUpload

Special Sauce
  • 5,338
  • 2
  • 27
  • 31