I am trying to write an HTTP Module that will add server variables to the Request.ServerVariables collection. If I try to modify the collection I receive an exception that states:
Cannot directly modify server variables
Essentially our code uses the server variables written by the 3rd party ISAPI filter. The requirements for the 3rd party set up are too great to setup and maintain
on each and every developers box. So I am trying to find a way to write these values without having to have the 3rd party ISAPI filter available at all times, thus allowing us to sandbox our machines.
Or you can use a Application variable for sharing within the whole application.
Application.Lock();
Application["AppName"] = "My Application";
Application.UnLock();
If you can't use cookies then you shouldn't be using header variables
either as header variables are easy to find with a simple http sniffer.
I'm thinking that you really should go with the suggestion of using a
database or some other shared server side storage location for holding
this value. Anyone that would go to the trouble of opening your cookie
would probably not have too much problem running something like Fiddler
(or any number of other tools) to see what is inside the headers for the
page. Also from a security standpoint, you probably don't want to pass
anything to the client that you are worried about getting hacked, it is
better to keep it at the server and use an authentication mechanism to
get to it each time it is needed.
I hope the above information will be helpful. If you have any issues or concerns, please let me know. It's my pleasure to be of assistance
Best Regards,
__________________________________________________
Sincerely,
Rex Lin
Microsoft Online Community Support
If there is any question or the issue is not resolved, please feel free to mark the thread as not resolved
As stated in the original post we have code that reads the Server Variables and the variables are populated by a 3rd party app. I am trying to simulate the third party app. To use the Context.Items would mean having to change already existing code which
at this point is not an option. Also this is ALL server side information, not client. So cookies/Headers don't apply here. Not sure why you were suggesting headers/cookies.
In order to get your own custom server variables, I think you need to reinvent the wheel and create your own implementation of a HttpWorkerRequest object. All variants ASP.NET uses are created internally by a factory and doesn't allow for extensions in any
way, so no hope there.
The HttpRequest.ServerVariables property (a NameValueCollection) is set readonly after populating all the variables. So if you really really need it, your only option that might be left is to create some kind of black magic HttpModule that uses a bit of
reflection to make that collection writable again and add your custom server variables.
Disclaimer: I don't know if that approach will work, but I'm almost 100% sure that you can't do anything to that ServerVariables collection after .NET has populated it for you.
So if you take that approach I wish you good luck.
Reflection did the trick, and was it pretty nasty [:D]
In intrest in sharing the solution with everyone, the following is the code I used. this was placed in my Begin Init of the HTTP Module. However, I'm guessing it could be placed in a few other events, I just chose this one for testing.
This looks like what i need, thoung i need to alter the UserAgent in the request.
Background:
I need to write a HTTP module that alters the UserAgent of the Request. This might seem like at stupid (or dangerous) thing to do, but it's what i need to do. Unfortunately i can't tell you why because of company secrets and bla bla bla. :-)
I assume i can use the method above to make the request writable. Then i just need a method to write to the UserAgent property.
I found the following article http://blogs.tedneward.com/2005/11/21/The+Immutable+String.aspx.From
that i wrote a HttpModule in C# that alters the Request.UserAgent the same way. (The UserAgent is normally ReadOnly)Now this method works fine while running my site on IIS 5.1 on XP machine. But when running
the site on IIS 7.0 (Vista), nothing happens.Literally nothing happens. The code runs smoothly with no errors (I’ve single stepped it) but the UserAgent has not changed? Code
that I used was:
private void addServerVariable(HttpApplication application)
{
//Add key/value-pairs to the ServerVaiables collection
//http://forums.asp.net/t/1125149.aspx - start
BindingFlags temp = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
MethodInfo insertInPlace = null;
MethodInfo appendInPlace = null;
MethodInfo fillStringChecked = null;
Type type = application.Request.UserAgent.GetType();
MethodInfo[] methods = type.GetMethods(temp);
foreach (MethodInfo method in methods)
{
switch (method.Name)
{
case "InsertInPlace": insertInPlace = method;
break;
case "AppendInPlace": appendInPlace = method;
break;
case "FillStringChecked": fillStringChecked = method;
break;
}
}
string strUserAgent = "FiSh HeAd";
//InsertInPlace arguments: index where to insert(int), chararray to insert(char[]), starting index in chararray(int), number of chars to insert(int), total length(int)
object[] values = { (int)0, strUserAgent.ToCharArray(), (int)0, (int)strUserAgent.Length, (int)strUserAgent.Length, (int)strUserAgent.Length };
insertInPlace.Invoke(application.Request.UserAgent, values);
//http://forums.asp.net/t/1125149.aspx - end
}
Any ideas why this would work on IIS 5.1 and not on IIS 7.0?
I'm using HttpModule to capture requests to the web server. Before
processing the page I'd like to check the values contained in some keys
of the Request.Form collection and according to some logic change if
necessary. I'd like to do this when BeginRequest event is fired. The
problem is that the Request.Form collection is readonly.
ThisBytes5
Member
101 Points
48 Posts
Adding servervariables
Jun 22, 2007 11:28 AM|LINK
Cannot directly modify server variables
Essentially our code uses the server variables written by the 3rd party ISAPI filter. The requirements for the 3rd party set up are too great to setup and maintain on each and every developers box. So I am trying to find a way to write these values without having to have the 3rd party ISAPI filter available at all times, thus allowing us to sandbox our machines.
Rex Lin - MS...
All-Star
17422 Points
2116 Posts
Re: Adding servervariables
Jun 26, 2007 02:35 AM|LINK
HI, ThisBytes5 :
How about using Context.Items?
Or you can use a Application variable for sharing within the whole application.
Application.Lock();
Application["AppName"] = "My Application";
Application.UnLock();
If you can't use cookies then you shouldn't be using header variables
either as header variables are easy to find with a simple http sniffer.
I'm thinking that you really should go with the suggestion of using a
database or some other shared server side storage location for holding
this value. Anyone that would go to the trouble of opening your cookie
would probably not have too much problem running something like Fiddler
(or any number of other tools) to see what is inside the headers for the
page. Also from a security standpoint, you probably don't want to pass
anything to the client that you are worried about getting hacked, it is
better to keep it at the server and use an authentication mechanism to
get to it each time it is needed.
I hope the above information will be helpful. If you have any issues or concerns, please let me know. It's my pleasure to be of assistance
__________________________________________________
Sincerely,
Rex Lin
Microsoft Online Community Support
If there is any question or the issue is not resolved, please feel free to mark the thread as not resolved
ThisBytes5
Member
101 Points
48 Posts
Re: Adding servervariables
Jul 03, 2007 01:40 PM|LINK
As stated in the original post we have code that reads the Server Variables and the variables are populated by a 3rd party app. I am trying to simulate the third party app. To use the Context.Items would mean having to change already existing code which at this point is not an option. Also this is ALL server side information, not client. So cookies/Headers don't apply here. Not sure why you were suggesting headers/cookies.
Thanks
Wayne
vvhagen
Member
314 Points
49 Posts
Re: Adding servervariables
Jul 03, 2007 11:39 PM|LINK
Wayne,
In order to get your own custom server variables, I think you need to reinvent the wheel and create your own implementation of a HttpWorkerRequest object. All variants ASP.NET uses are created internally by a factory and doesn't allow for extensions in any way, so no hope there.
The HttpRequest.ServerVariables property (a NameValueCollection) is set readonly after populating all the variables. So if you really really need it, your only option that might be left is to create some kind of black magic HttpModule that uses a bit of reflection to make that collection writable again and add your custom server variables.
Disclaimer: I don't know if that approach will work, but I'm almost 100% sure that you can't do anything to that ServerVariables collection after .NET has populated it for you.
So if you take that approach I wish you good luck.
Victor
ThisBytes5
Member
101 Points
48 Posts
Re: Adding servervariables
Jul 05, 2007 11:55 AM|LINK
Reflection did the trick, and was it pretty nasty [:D]
In intrest in sharing the solution with everyone, the following is the code I used. this was placed in my Begin Init of the HTTP Module. However, I'm guessing it could be placed in a few other events, I just chose this one for testing.
void context_BeginRequest(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; BindingFlags temp = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static; MethodInfo addStatic = null; MethodInfo makeReadOnly = null; MethodInfo makeReadWrite = null; Type type = application.Request.ServerVariables.GetType(); MethodInfo[] methods = type.GetMethods(temp); foreach (MethodInfo method in methods) { switch (method.Name) { case "MakeReadWrite": makeReadWrite = method; break; case "MakeReadOnly": makeReadOnly = method; break; case "AddStatic": addStatic = method; break; } } makeReadWrite.Invoke(application.Request.ServerVariables, null); string[] values = { "NewVar1", "Test" }; addStatic.Invoke(application.Request.ServerVariables, values); makeReadOnly.Invoke(application.Request.ServerVariables, null); }Thanks again for the help and direction, Hope this helps someone else out there.Wayne
mreynolds
Member
11 Points
4 Posts
Re: Adding servervariables
Aug 24, 2007 04:10 PM|LINK
Just used this today when I was trying to simulate what IBM's Tivoli Access Manager does to my .NET application in production. Thank you!
forty7
Member
2 Points
2 Posts
Re: Adding servervariables
Apr 01, 2008 09:31 PM|LINK
I just used this today to simulate Siteminder's Header variables on local development machine. Thank you!
esbenr
Member
51 Points
18 Posts
Re: Adding servervariables
May 13, 2008 06:39 AM|LINK
This looks like what i need, thoung i need to alter the UserAgent in the request.
Background:
I need to write a HTTP module that alters the UserAgent of the Request. This might seem like at stupid (or dangerous) thing to do, but it's what i need to do. Unfortunately i can't tell you why because of company secrets and bla bla bla. :-)
I assume i can use the method above to make the request writable. Then i just need a method to write to the UserAgent property.
Can anybodu help me out here?
Thanks in advance.
Esben Rasmussen
esbenr
Member
51 Points
18 Posts
Re: Adding servervariables
May 14, 2008 09:43 AM|LINK
private void addServerVariable(HttpApplication application) { //Add key/value-pairs to the ServerVaiables collection //http://forums.asp.net/t/1125149.aspx - start BindingFlags temp = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static; MethodInfo insertInPlace = null; MethodInfo appendInPlace = null; MethodInfo fillStringChecked = null; Type type = application.Request.UserAgent.GetType(); MethodInfo[] methods = type.GetMethods(temp); foreach (MethodInfo method in methods) { switch (method.Name) { case "InsertInPlace": insertInPlace = method; break; case "AppendInPlace": appendInPlace = method; break; case "FillStringChecked": fillStringChecked = method; break; } } string strUserAgent = "FiSh HeAd"; //InsertInPlace arguments: index where to insert(int), chararray to insert(char[]), starting index in chararray(int), number of chars to insert(int), total length(int) object[] values = { (int)0, strUserAgent.ToCharArray(), (int)0, (int)strUserAgent.Length, (int)strUserAgent.Length, (int)strUserAgent.Length }; insertInPlace.Invoke(application.Request.UserAgent, values); //http://forums.asp.net/t/1125149.aspx - end }Any ideas why this would work on IIS 5.1 and not on IIS 7.0?
ghootifarang...
Member
2 Points
4 Posts
Re: Adding servervariables
Jun 20, 2010 09:29 AM|LINK
I'm using HttpModule to capture requests to the web server. Before
processing the page I'd like to check the values contained in some keys
of the Request.Form collection and according to some logic change if
necessary. I'd like to do this when BeginRequest event is fired. The
problem is that the Request.Form collection is readonly.
Is there any way to accomplish this task ?
Thanks is advance