问题
I have a really strange problem with WebRequest in a ServiceStack web application (hosted by XSP on Mono). It seems that the registration of request modules works in a very strange way; I am using WebRequest to create an HTTP request, and it is failing because it was not able to find a creator for that "prefix" (HTTP).
The exception I am seeing is NotSupportedException
, and I was able to track it to the fact that no creator is registered for the HTTP prefix (I am hitting https://github.com/mono/mono/blob/master/mcs/class/System/System.Net/WebRequest.cs, around line 479)
EDIT: more details: NotSupportedException
is thrown by WebRequest.GetCreator
, which uses the URL prefix as a key to choose which creator to return; in my case, a HttpRequestCreator
. The exception is thrown because there is no creator registered for the "HTTP" prefix (actually, there are no creators at all).
So I searched around a little bit, dug into Mono sources, and found that modules are (or should be) added to the webRequestModules section of system.web in one of the various *.config files.
I looked at my machine.config file, and there it is:
System.Net.HttpRequestCreator, System, Version=4.0.0.0
Looking at WebRequest Mono sources it seems that prefixes are added from configuration(s) indeed, inside the class static constructor (not a good choice, IMHO, but still.. should work).
To test it, I tried to add an HttpRequestCreator
to system.net/webRequestModules
in my web.config
; this is loaded by XSP/Mono and results in a duplicate key exception (which is expected, since HttpRequestCreator should be already loaded, as it is already present in machine.config).
Even stranger: if I add a mock handler for Http, like this:
bool res = System.Net.WebRequest.RegisterPrefix ("http", new MyHttpRequestCreator ());
Debug.Assert (res == false);
the assertion sometimes pass... sometimes not! (RegisterPrefix returns "false" if a creator for the same prefix is already registered; I expect it always to return false, but this is not the case! Again, it is completely random)
When the registration "fails" (i.e., returns false because an "HTTP" prefix is already registered) then the WebRequest can create requests for HTTP. It is as if calling RegisterPrefix "wakes up" the static constructor and let it run.
I am perplexed: it seems like a race condition in the execution of the static constructor of WebRequest, but this does not make sense (the runtime protects static constructors with a lock, IIRC)
What am I missing? How could I solve, or work around this problem? Is it my fault (misunderstanding or missing something) or does it look like a Mono bug, and therefore should I submit it?
Details:
mono --version Mono JIT compiler version 3.0.6 (Debian 3.0.6+dfsg-1~exp1~pre1)
(Possibly related, unanswered question: HTTP protocol not supported in WebRequest under mono)
来源:https://stackoverflow.com/questions/17657145/troubles-using-webrequest-in-mono