Question about GetServerVariable QUERY_STRING

I recently got this question about the behavior of QUERY_STRING values. Unfortunately, server variable values are more a matter of art than science, as I will shortly describe…


Hi David,

I am having an interesting problem. I have written an ISAPI filter that pulls information like the REMOTE_ADDR, AUTH_USER, QUERY_STRING, SERVER_PORT, and SERVER_NAME. I store this information and pass it to another program that uses it.

The problem that I am having is that on IIS 6.0, everything works as I would expect. Unfortunately, I am not seeing the same behavior on IIS 5.0. I pull everything the same way except the QUERY_STRING always returns empty. I am pretty sure that it isn’t the code around it because I can change it to ALL_RAW or AUTH_USER and get information printed.

I know that on ISA, the query string is not supported, but I am not using ISA. Am I missing something?

So I have checked other information on it, as well. The function is always returning TRUE in 2000 and 2003. I am checking the GetLastError just to make sure, and it returns a 0 also.

Any advice?



When it comes to the expected value of a Server Variable, it completely depends on the filter event within which you retrieve the server variable and sometimes even ordering/timing.

For example, server variable values are not always populated right from the start. QUERY_STRING is not going to be populated in events like SF_NOTIFY_READ_RAW_DATA or SF_NOTIFY_PREPROC_HEADERS because IIS has not yet parsed the request and hence cannot legitimately populate that server variable. In those cases, IIS GetServerVariable() should return true and an empty string.

Now, you should note that server variable values will change over the lifetime of request processing. For example, it is possible on the second SF_NOTIFY_READ_RAW_DATA event to find QUERY_STRING populated and valid. This is because the first SF_NOTIFY_READ_RAW_DATA was for the headers (and QUERY_STRING is invalid since headers were not parsed yet), and after the headers are parsed and QUERY_STRING populated, the subsequent SF_NOTIFY_READ_RAW_DATA are for entity body – so QUERY_STRING would be rightfully valid.

Then again, sometimes IIS may return true and non-empty values for server variables in events that it should not… which is technically a bug, but if you tried to rely on those values, your ISAPI has a serious bug as well. For example, try to retrieve the REMOTE_ADDR server variable in SF_NOTIFY_END_OF_NET_SESSION, and it can come back with a valid value… but clearly, the connection has already ended, so the value is bogus and useless for communications usage.

Ordering also matters. For example, retrieving the PATH_TRANSLATED server variable will trigger participating SF_NOTIFY_URL_MAP filters who may/not manipulate pszPhysicalPath. This means that depending on arbitrary ISAPI Filter ordering/behavior, an ISAPI Filter can retrieve different values for PATH_TRANSLATED, even within the same filter event… and once again, this behavior is perfectly valid and permissible. A similar class of behavior exists with WriteClient() and SendResponseHeader because they allow a filter to prematurely trigger SF_NOTIFY_SEND_RAW_DATA and SF_NOTIFY_SEND_RESPONSE events, and the state of server variables may be different than the normal sequence.

So, the answer to your question really depends on what filter event and possibly ordering of other filters on IIS. But, I do not have that information so I cannot say for certain what is going on in your situation. I suspect you are looking at some quirks related to processing subsequent SF_NOTIFY_READ_RAW_DATA based on some of the behavior possibilities I described above.

FYI: since ISA Server’s implementation of ISAPI Filter is completely separate and unrelated to IIS ISAPI Filter, I would not try to draw any sort of parallel expectations between them.


Comments (4)

  1. qiyang says:


  2. Jeff Parker says:

    Hmm, now yes I agree that the server variable can change. But thinking of a .net http module or handler be a better sollution? I really haven’t created an isapi anything since .net came out, just haven’t had the need. That would allow you to use the HttpContext class which this should always have this information populated. Now thats not saying that it couldn’t change later but you should have most everything populated initially or am I wrong in thinking this way?

  3. David Wang says:

    Jeff – it all depends on what you are trying to do, which you did not explain so I cannot make a judgement on whether one is "better" than the other.

    I can think of situations where ISAPI Filter is the only possible solution, and I can think of some situations where HttpModule / HttpHandler is the only solution.

    From the perspective of comparison, HttpContext is like fetching ServerVariables inside of an ISAPI Extension, so your comparison is not really comparable. Add on top the fact that HttpModule is able to modify these variables as the ASP.Net pipeline executes (on top of the IIS pipeline), and you should see how the two are completely different and complex in their own way.

    This all gets resolved in IIS7 Integrated Mode.