context.Response.Filter breaks processing of ISAPI Extension

  • Thread starter Thread starter Dima67
  • Start date Start date
D

Dima67

Hi,

I am substituting an old ISAPI filter with a HttpModule using VS2008 and I
got a set of problems.


The old ISAPI filter works this way:

1) It gets a request from a client browser

2) then it figures out if this request has to be re-directed to a different
web application. (It depends on request’s parameters)

3) If this request should not be re-directed, then the ISAPI filter passes
it to an ISAPI extension on the local server and filters the response before
returning it to the client.

4) If this request should be re-directed, then the ISAPI filter re-directs
the request and filters its response before returning it to the client.


To do that in Visual Studio 2008, I created a HttpModule, added a handler
for HttpApplication.BeginRequest event and in the event handler I added a
wrapping filter:

public void On_BeginRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Filter = new FilterStream(context.Response.Filter);
}
}

The FilterStream does all the required filtering.

But this approach does not work because of the following problems:

Problem 1:

Without specifying the wrapping filter, IIS properly resolves default
document name (which is my ISAPI extension DLL) , passes requests to the
ISAPI DLL and everything works fine.

But when I assign the wrapping filter (i.e.
Application.Context.Response.Filter = new …), IIS starts to verify existence
of a resource specified in URL. The URL points to my ISAPI extension and,
therefore, IIS does not find an existing file with such name.

The error is:†A first chance exception of type 'System.Web.HttpException'
occurred in System.Web.dll
Additional information: File does not exist.â€.

How to avoid such error? How to prevent IIS from checking existance of the
resource when a wrapping filter is assigned to the request?



Problem 2:

I read that redirect requests reset existing chain of wrapping filters. I.e.
a filter assigned to Application.Context.Response.Filter property will never
be called when the page is redirected.

But I need to get a response from the re-directed request and filter it. How
it can be done with .Net framework 3.5 (VS2008).
 
Hi,
But when I assign the wrapping filter (i.e.
Application.Context.Response.Filter = new …), IIS starts to verify existence
of a resource specified in URL. The URL points to my ISAPI extension and,
therefore, IIS does not find an existing file with such name.

The error is:†A first chance exception of type 'System.Web.HttpException'
occurred in System.Web.dll
Additional information: File does not exist.â€.

How to avoid such error? How to prevent IIS from checking existance of the
resource when a wrapping filter is assigned to the request?

You should create your own IHttpHandler that will handle your request.
It should do exactly the same that was done by the ISAPI extension.
I read that redirect requests reset existing chain of wrapping filters. I.e.
a filter assigned to Application.Context.Response.Filter property will never
be called when the page is redirected.

But I need to get a response from the re-directed request and filter it. How
it can be done with .Net framework 3.5 (VS2008).

Please describe what you mean on redirection and how you do that because
there are too many possible meanings/solutions.

Marvin
 
Currently the new .Net pased HttpModule does not do redirection. I am trying
to make context.Response.Filter work.

Any idea, why as soon as context.Response.Filter is assigned, IIS stops to
understand that the specified URL should not be checked against physically
present resources and just needs to be passed to the registered ISAPI
Extension?
 
Dima67 said:
Currently the new .Net pased HttpModule does not do redirection. I am trying
to make context.Response.Filter work.

Any idea, why as soon as context.Response.Filter is assigned, IIS stops to
understand that the specified URL should not be checked against physically
present resources and just needs to be passed to the registered ISAPI
Extension?

The request has to be handled anyway. I don't really understand your
setup but note that unless you are using IIS 7.0 Integrated Pipeline
mode, you aren't able to mix ASP.NET with an ISAPI extension. Older
versions and classic mode will not allow this.

Also note that if you get a HttpException that means that the request is
being processed by ASP.NET rather than your ISAPI extension. Your ISAPI
extension is invoked if you either request the DLL file as an ISAPI
extension or map a file extension to the ISAPI extension. If you haven't
done any of these, then your ISAPI extension will not be invoked.

If none of this helps please explain your IIS and ASP.NET configuration
and/or the flow how your components interact.

Marvin
 
Hi Marvin,

I have a virtual directory and an ISAPI extension configured as a default
content page (Virtual directory properties/ Documents tab/ “Enable Default
content page†pan with the checkbox checked and my ISAPI extension DLL added
to the list box).

To be able to use ASP with this ISAPI extension I added a Wildcard
Application Map for my virtual directory (Virtual directory properties/
“Configuration…†button/ “Mapping†tab/ “Wildcard application maps (order of
implementation) list box).

After that, I compiled my HttpModule and put its assembly to the Bin
sub-directory of my virtual directory.

After that, I registered the HttpModule in Web.config file in my virtual
directory.

In the HttpModule I added a handler to HttpApplication.BeginRequest event.

Till this point everything works fine. Requests come through my HttpModule,
then goes to my ISAPI extension and returns to the client browser.

But as soon as I add a wrapping filter like this:

public void On_BeginRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Filter = new
FilterStream(context.Response.Filter);// This line causes problems
}

I see the following exception: “The resource cannot be found.â€

The stack looks this way:

System.Web.dll!System.Web.StaticFileHandler.GetFileInfo(string
virtualPathWithPathInfo, string physicalPath, System.Web.HttpResponse
response) + 0x1f2 bytes

System.Web.dll!System.Web.StaticFileHandler.ProcessRequestInternal(System.Web.HttpContext context = {System.Web.HttpContext}) + 0x99 bytes

System.Web.dll!System.Web.DefaultHttpHandler.BeginProcessRequest(System.Web.HttpContext
context, System.AsyncCallback callback = {Method = {Void
OnAsyncHandlerCompletion(System.IAsyncResult)}}, object state = null) + 0x140
bytes

System.Web.dll!System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() + 0x249 bytes

System.Web.dll!System.Web.HttpApplication.ExecuteStep(System.Web.HttpApplication.IExecutionStep
step = {System.Web.HttpApplication.CallHandlerExecutionStep}, ref bool
completedSynchronously = true) + 0x9c bytes

System.Web.dll!System.Web.HttpApplication.ApplicationStepManager.ResumeSteps(System.Exception error) + 0x133 bytes

System.Web.dll!System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(System.Web.HttpContext
context, System.AsyncCallback cb, object extraData) + 0x7c bytes

System.Web.dll!System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest
wr = {System.Web.Hosting.ISAPIWorkerRequestInProcForIIS6}) + 0x17c bytes

System.Web.dll!System.Web.HttpRuntime.ProcessRequestNoDemand(System.Web.HttpWorkerRequest wr) + 0x63 bytes

System.Web.dll!System.Web.Hosting.ISAPIRuntime.ProcessRequest(System.IntPtr
ecb, int iWRType) + 0x11c bytes
[Appdomain Transition]
[Native to Managed Transition]
webengine.dll!BufferPoolReleaseBuffer() + 0x1bb bytes
[Frames below may be incorrect and/or missing, no symbols loaded for
webengine.dll]
webengine.dll!PerfSetCounter() + 0x83 bytes
webengine.dll!PerfSetCounter() + 0x50 bytes
kernel32.dll!GetModuleHandleA() + 0xdf bytes


So, the exception happens not in my code. For some reason ASP (or IIS?)
tries to access my ISAPI extension like a file, does not find it and throws
the exception.

Looks like a clear bug for me. Why existence of a wrapping filter in
Response property causes IIS to verify existence of the specified default
document?
 
Dima67 said:
I have a virtual directory and an ISAPI extension configured as a default
content page (Virtual directory properties/ Documents tab/ “Enable Default
content page†pan with the checkbox checked and my ISAPI extension DLL added
to the list box).

Please let me know the default page name.
To be able to use ASP with this ISAPI extension I added a Wildcard
Application Map for my virtual directory (Virtual directory properties/
“Configuration…†button/ “Mapping†tab/ “Wildcard application maps (order of
implementation) list box).

And the actual mapping (extension and DLL you use) because I don't know
if ASP, ASP.NET, or a custon ISAPI extension is that.
System.Web.dll!System.Web.StaticFileHandler.GetFileInfo(string
virtualPathWithPathInfo, string physicalPath, System.Web.HttpResponse
response) + 0x1f2 bytes

The problem is that ASP.NET tries to handle the request.
System.Web.dll!System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest
wr = {System.Web.Hosting.ISAPIWorkerRequestInProcForIIS6}) + 0x17c bytes

You haven't mentioned but this seems to be IIS 6. As I said in my
previous post if you want to mix ASP.NET with other ISAPI extensions you
have to use IIS 7.0 (or later) in Integrated Pipeline mode.
Till this point everything works fine. Requests come through my HttpModule,
then goes to my ISAPI extension and returns to the client browser.

But as soon as I add a wrapping filter like this:

If you are using IIS 6 I don't even understand how can everything be
fine then everything be ruined just by installing an ASP.NET filter
because the whole request is either handled by ASP.NET or your ISAPI
filter, not both.

Marvin
 
Hi Marvin,

Thank you for the following up on this issue.

Please, see my comments below.

--
Best regards, Dima.


Marvin Landman said:
Please let me know the default page name.

The default page name is myIsapi.DLL

And the actual mapping (extension and DLL you use) because I don't know
if ASP, ASP.NET, or a custon ISAPI extension is that.


The problem is that ASP.NET tries to handle the request.


You haven't mentioned but this seems to be IIS 6. As I said in my
previous post if you want to mix ASP.NET with other ISAPI extensions you
have to use IIS 7.0 (or later) in Integrated Pipeline mode.

This is IIS6. I did not find any info confirming that I cannot mix ASP.NET
with other ISAPI extensions. ASP.NET is just a ISAPI Filter. When it does not
find ASP-specific tags in the page code, it does nothing.
What is a problem with it?
If you are using IIS 6 I don't even understand how can everything be
fine then everything be ruined just by installing an ASP.NET filter
because the whole request is either handled by ASP.NET or your ISAPI
filter, not both.

IIS6 allows to use multiple ISAPI filters. So, what's wrong with adding my
ISAPI filter after ASP.NET one?
 
Hi,

The problem is that ASP.NET is an ISAPI extension just like your
extension so you cannot use both at the same time. Only one extension
can handle a request. Also note that ASP.NET cannot interact requests
not handled by ASP.NET prior to IIS 7.

ASP.NET has a filter but that is only supporting some functionalities
not allowing you to filter the request or the response body.

And I am not sure that you can use ASP.NET stream filters for requests
other than that handled by ASP.NET in IIS 7. Even if you are able to do
that in IIS 7, I can assure you that IIS 6 has no support for that.

Marvin

Dima67 wrote:
This is IIS6. I did not find any info confirming that I cannot mix ASP.NET
with other ISAPI extensions. ASP.NET is just a ISAPI Filter. When it
does not
find ASP-specific tags in the page code, it does nothing.
What is a problem with it?

IIS6 allows to use multiple ISAPI filters. So, what's wrong with adding my
ISAPI filter after ASP.NET one?
 
Hi Marvin,

Please, correct me if I am wrong, but ASP.Net is an ISAPI Filter, not an
ISAPI extension. Therefore, it should work fine with other ISAPI filters
because IIS6 allows multiple ISAPI Filters.

If you know where Microsoft describes ASP.Net as ISAPI Extention, please,
let me know. It will save a lot of time for me.
 
Hi,

Look for C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll
that is the ISAPI extension that handles ASP.NET requests.

C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_filter.dll on the
other hand just protects application forders (bin, App_Data, etc.) and
helps using cookieless session state but does not execute any managed or
user defined code.

Marvin
 
Back
Top