Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Accessing Request.InputStream / Request.BinaryRead *as the request is occuring*: How???

182 views
Skip to first unread message

Brian Birtle

unread,
Oct 9, 2003, 1:46:09 AM10/9/03
to
I am trying to create a module which displays a progress meter while the
user is uploading files to my ASP/ASP.NET application. I was able to do this
in ASP classic using Request.BinaryRead and the ADODB.Stream classes. But I
have run into a brick wall with ASP.NET because of the following:

* Request.BinaryRead() thread blocks until the entire request is completely
read

* Access to the Request.InputStream property thread blocks until the entire
request is completely read (cannot access this property of Request until the
request is finished)

* Can add a Request.Filter stream but it is never called until the entire
request is completely read

You can verify these facts easily by uploading a large file and attaching a
debugger, set a breakpoint somewhere, then type "Request.InputStream" in the
command window - VS.NET will appear to lock up until the file upload has
completely finished. (I also tested in other ways to confirm it isn't a
strange quirk of VS.NET) Note than Page_OnInt and Page_OnLoad don't even get
fired until the entire request is read - but Application.On_BeginRequest
does.

Because of this, my "progress meter" jumps suddenly from 0% to 100% once the
upload has completed... obviously this won't work. I tried building my code
into Application.On_BeginRequest, Page.On_Init, Page.On_Load, an
HttpHandler, and even a web service and the above all holds true - it seems
to be the behavior of the HttpContext and related classes.

Please tell me there's a workaround? Some configuration setting I can set? A
fancy trick? I can't believe Microsoft would allow a feature degradedation
from ASP to ASP.NET - there must be something... I sketched out a messy
solution where I can read in the uploaded file request using ASP classic and
then redirect to an ASP.NET script which would read and parse the uploaded
data from disk. But it's a serious hassle! Also it's possible using an ISAPI
filter but this is worse for us even than using an ASP classic solution for
many reasons.

Thanks for your time.

Brian Birtle
WWWbr...@YYYbirtle.comZZZ
Web Application Developer - VPD Group
International Technigroup Incorporated
http://www.iti-global.com/


John Saunders

unread,
Oct 9, 2003, 3:53:51 AM10/9/03
to
"Brian Birtle" <WWWbr...@YYYbirtle.comZZZ> wrote in message
news:ew%23sriij...@TK2MSFTNGP11.phx.gbl...

> I am trying to create a module which displays a progress meter while the
> user is uploading files to my ASP/ASP.NET application. I was able to do
this
> in ASP classic using Request.BinaryRead and the ADODB.Stream classes. But
I
> have run into a brick wall with ASP.NET because of the following:
...

> Please tell me there's a workaround? Some configuration setting I can set?
A
> fancy trick? I can't believe Microsoft would allow a feature degradedation
> from ASP to ASP.NET - there must be something... I sketched out a messy
> solution where I can read in the uploaded file request using ASP classic
and
> then redirect to an ASP.NET script which would read and parse the uploaded
> data from disk. But it's a serious hassle! Also it's possible using an
ISAPI
> filter but this is worse for us even than using an ASP classic solution
for
> many reasons.

Sorry, but you can't do what you want that way. ASP.NET works as a purely
request-response protocol. The output of a byte on the server has nothing to
do with when the client will receive the byte, except that the client
generally receives a byte some time after it is sent. And even if there were
a close correspondence between when a byte was sent and when it was
received, you have no control at all over when the client chooses to process
the byte or when it chooses to display it.

If you search for "progress bar" or "progress meter" in this newsgroup,
you'll find many discussions on how to accomplish something like what you
wanted.
--
John Saunders
Internet Engineer
john.s...@surfcontrol.com


Brian Birtle

unread,
Oct 11, 2003, 2:32:43 AM10/11/03
to
John, Thanks for responding.

I should clarify that my question is not about creating a progress
meter per se as I have already successfully created one using ASP
classic. My question is, generally speaking, why do
Request.BinaryRead, Request.InputStream, and Request.Filter thread
block and is there a workaround?

Here is some example code to show what I'm talking about (put in your
global.asax or class that derives from HttpApplication):

... On_BeginRequest(...)
{
////This line gets executed right when the HTTP connection is
// opened (before even any of the HTTP request is read):
Application["UploadState"] = "started";
...

////Following line thread blocks until entire request is read
(even
// though I have only requested to read the first 10 bytes of
the
// incoming HTTP request stream (POSTed data).) Note this could
be
// 30 minutes if the uploaded file is large and/or connection is
// slow. Also note that in ASP classic the same call will return
// immediately after the first 10 bytes are read (no thread
block):
byte[] firstTenBytes = Request.BinaryRead(10);


////Following line executes only after entire HTTP request has
been
// received:
Application["UploadState"] = "finished";

////This line would also thread block, if the BinaryRead line
were
// commented out:
Stream request = Request.InputStream;
// Note I have not even called any methods on the InputStream -
it
// seems the InputStream property itself is thread blocking.

////This line does not thread block:
Request.Filter = new MyFilterClass();

////but MyFilterClass is never called by ASP.NET (the Read method
in
// particular) until the entire request is read, thus the Filter
class
// seems useless of my purposes.

} ...

Can any of you gurus out there help me? Surely SOMEBODY knows the
answer??? I figure there's got to be an @ flag I can set in the aspx
page, or in web.config, or something - but I have searched forever and
can't find a way.

Regarding your comment about request-response and "no can do", you are
correct about generally speaking how HTTP and ASP.NET works and this
is indeed a mistake in thinking that many new developers make. But
actually what you do is stick Request.BinaryRead into a loop and as
the loop is occuring (as upload is being received) you update an
Application variable. Then in *a seperate* HTTP request (browser
window, spereate TCP-IP/HTTP thread/connection) you can query a script
like GetProgress.aspx which would return the Application variable and
a progress meter in HTML form (or in my case I use XMLHTTP and update
a progress meter with JavaScript but same principle).

Of course if somebody can describe to me a completely different way to
do the progress meter I'd abandon the above method. Actually we're
using a custom-built, really slick client-side IE ActiveX control for
the uploads (written in ATL C++), so my first attempt was to try and
figure out "bytes sent" from the client-side... but I can't find an
API function to do it (we're using a URL Moniker).

Finally, I have not seen a working, freeware, *pure ASP.NET* progress
meter solution and have searched for many hours. All the examples I've
found use either ASP classic, an ISAPI filter, or a VB 6 COM object.
So if anyone could forward me some source code or a URL I'd be very
grateful.

Thanks very much,
- Brian

"John Saunders" <john.saunders at surfcontrol.com> wrote in message news:<OPQcNqjj...@tk2msftngp13.phx.gbl>...

John Saunders

unread,
Oct 11, 2003, 5:49:21 AM10/11/03
to
"Brian Birtle" <brian_...@hotmail.com> wrote in message
news:b5e821b2.03101...@posting.google.com...

> John, Thanks for responding.
>
> I should clarify that my question is not about creating a progress
> meter per se as I have already successfully created one using ASP
> classic. My question is, generally speaking, why do
> Request.BinaryRead, Request.InputStream, and Request.Filter thread
> block and is there a workaround?

Yes. The workaround to synchronous behavior is to use an asynchronous
handler. See IHttpAsyncHandler in the documentation.

Even if you can find a way to not block until the entire request has been
read, I hope you realize that there is still no correspondence between the
time you receive a byte and the time the client sent it, except that you can
be certain the byte was sent before it was received. As an example, you
might read the first ten bytes very soon after the client sent them, but the
next ten bytes might be received after the client has finished sending the
entire request. If this is not acceptible, you should not be using HTTP.

>
> Here is some example code to show what I'm talking about (put in your
> global.asax or class that derives from HttpApplication):
>
> ... On_BeginRequest(...)
> {
> ////This line gets executed right when the HTTP connection is
> // opened (before even any of the HTTP request is read):
> Application["UploadState"] = "started";
> ...

I hope you meant Session and not Application, unless you can ensure that
there will never be more than one request at a time.

Brian Birtle

unread,
Oct 16, 2003, 9:09:02 AM10/16/03
to
John,
Thanks again for your post.

I saw the IHttpAsyncHandler class back when I was researching the
problem and thought "Eureka!" But when I looked into it it seems like
the purpose is actually to handle certain cases where the HTTP
*response* (not request) should be made based on external events -
like bytes read from a slow data stream which you've connected to from
the server... short answer is it doesn't seem to do what I need.

Unforunately I've been too busy to build a test case, but I suspect
since it's also based on the HttpContext/HttpRequest framework the
behavior will be the same as an HttpHandler, which has the same
thread-blocking problem.

Any other ideas?

- Brian

"John Saunders" <john.saunders at surfcontrol.com> wrote in message news:<#hGT5z9j...@TK2MSFTNGP10.phx.gbl>...

John Saunders

unread,
Oct 16, 2003, 9:58:00 AM10/16/03
to
"Brian Birtle" <brian_...@hotmail.com> wrote in message
news:b5e821b2.03101...@posting.google.com...
> John,
> Thanks again for your post.
>
> I saw the IHttpAsyncHandler class back when I was researching the
> problem and thought "Eureka!" But when I looked into it it seems like
> the purpose is actually to handle certain cases where the HTTP
> *response* (not request) should be made based on external events -
> like bytes read from a slow data stream which you've connected to from
> the server... short answer is it doesn't seem to do what I need.
>
> Unforunately I've been too busy to build a test case, but I suspect
> since it's also based on the HttpContext/HttpRequest framework the
> behavior will be the same as an HttpHandler, which has the same
> thread-blocking problem.
>
> Any other ideas?

Well, I know it's not _just_ a matter of the response being asynchronous.
The BeginProcessRequest method can initiate a chain of asynchronous events,
so at least the processing of the request can be done in parallel.

The question will be: is it the case that BeginProcessRequest is only called
after the entire request has been read in?


--
John Saunders
Internet Engineer
john.s...@surfcontrol.com

John Saunders

unread,
Oct 16, 2003, 10:11:07 AM10/16/03
to
"John Saunders" <john.saunders at surfcontrol.com> wrote in message
news:%23OdLK2%23kDH...@TK2MSFTNGP10.phx.gbl...

> "Brian Birtle" <brian_...@hotmail.com> wrote in message
> news:b5e821b2.03101...@posting.google.com...
> > John,
> > Thanks again for your post.
> >
> > I saw the IHttpAsyncHandler class back when I was researching the
> > problem and thought "Eureka!" But when I looked into it it seems like
> > the purpose is actually to handle certain cases where the HTTP
> > *response* (not request) should be made based on external events -
> > like bytes read from a slow data stream which you've connected to from
> > the server... short answer is it doesn't seem to do what I need.
> >
> > Unforunately I've been too busy to build a test case, but I suspect
> > since it's also based on the HttpContext/HttpRequest framework the
> > behavior will be the same as an HttpHandler, which has the same
> > thread-blocking problem.
> >
> > Any other ideas?
>
> Well, I know it's not _just_ a matter of the response being asynchronous.
> The BeginProcessRequest method can initiate a chain of asynchronous
events,
> so at least the processing of the request can be done in parallel.
>
> The question will be: is it the case that BeginProcessRequest is only
called
> after the entire request has been read in?

P.S. So you should go try the above and get back to us.

If BeginProcessRequest doesn't happen until the entire request has been read
in, then you're SOL as far as standard ASP.NET. This would leave you needing
to implement your own host for ASP.NET. See the Cassini web server at
http://asp.net for an example of this.

0 new messages