G
greendot
As many have found out, when .Net 1.1 SP1 was released, a few of the
network objects started complaining about HTTP protocol violations. I
know I experienced this quite a few times when dealing with web
services and most recently, trying to pull a simple page with the
System.Net.WebClient object (in .Net 2.0).
The solution everybody comes up with is editing the .config
(web.config, app.config, machine.config, or whatever.config) and make
sure the following info is there:
<configuration>
<system.net>
<settings>
<httpWebRequest useUnsafeHeaderParsing="true" />
</settings>
</system.net>
</configuration>
This is a global setting, though. It's beyond my understanding as to
why MS didn't imaging the situation where a programmer might want to
toggle this in code. Perhaps intranet sites do not need the strict
security an external sites do.
There were a few posts that said it was possible to programmatically
alter the System.Configuration items to do all of this but I was never
able to find an example and I wasn't able to find any members of
System.Configuration that allowed for writing. It seemed to be a
"read-only" baby. (until .Net 2.0, but even now it doesn't look like
you can alter the same areas the http controls are looking.)
So I coded up something that probably isn't the most elegant solution,
but it gets the job done in what I was needing to do. Maybe somebody
else will find it useful. Or at least provide feedback on what might
be wrong with this.
It consists of creating a new app domain space with a custom config
file that does contain the needed setting.
I make no guarantees that the following code works. I know it worked
before I pasted it here into the browser, but I had to do a bunch of
formatting changes to get the word-wrapping to look good.
Function PullUrlToFile(ByVal url As String, ByVal filename As String)
As Integer
' set up a new app domain to read in a custom .config file
Dim config As String = "<configuration><system.net><settings>" _
"<httpWebRequest
useUnsafeHeaderParsing=""true""/>" _
"</settings></system.net></configuration>"
Dim tmpConfigFile As String = System.IO.Path.GetTempFileName
Unslurp(tmpConfigFile, config) ' function that dumps text to file
If (Not System.IO.File.Exists(tmpConfigFile)) Then _
Throw New System.IO.FileNotFoundException( _
"Unable to create custom configuration file.", tmpConfigFile)
Dim exeAssembly As String = Assembly.GetEntryAssembly.FullName
' Construct and initialize settings for a second AppDomain.
dim info as System.AppDomainSetup =
AppDomain.CurrentDomain.SetupInformation
Dim ads As New AppDomainSetup()
ads.ApplicationBase = info.ApplicationBase
ads.ApplicationName = info.ApplicationName
ads.ConfigurationFile = tmpConfigFile
Dim html As String = ""
Try
' Create the second Domain.
Dim ad2 As AppDomain = _
AppDomain.CreateDomain("DYNAMIC_CONFIG", Nothing, ads)
Try
Dim proxy As UrlSlurper = _
CType(ad2.CreateInstanceAndUnwrap(exeAssembly, _
GetType(UrlSlurper).FullName), UrlSlurper)
html = proxy.SlurpUrl(url)
Finally
' Unload the second AppDomain. This deletes its object and
' invalidates the proxy object.
AppDomain.Unload(ad2)
End Try
Catch ex As Exception
Console.WriteLine("Exception spawning secondary Domain")
Console.WriteLine("{0}", ex.Message)
If (ex.InnerException IsNot Nothing) Then
Console.WriteLine(ex.InnerException.Message)
End If
Return -5
End Try
' extra code deleted to ease the eyes
End Function
Public Class UrlSlurper
Inherits MarshalByRefObject
Public Function SlurpUrl(ByVal url As String) As String
Using www As New System.Net.WebClient
www.Headers.Add(Net.HttpRequestHeader.UserAgent, _
[String].Format("Mozilla/4.0 (compatible; MSIE 6.0; " + _
"Windows NT 5.2; .NET CLR {0}",
Environment.Version.ToString))
Console.WriteLine("Pulling: {0}", url)
Dim data As System.IO.Stream = www.OpenRead(url)
Try
Dim reader As New System.IO.StreamReader(data)
Try
Return reader.ReadToEnd()
Finally
reader.Close()
End Try
Finally
data.Close()
End Try
End Using
End Function
End Class
That's it. Hope it helps somebody.
-Joe
network objects started complaining about HTTP protocol violations. I
know I experienced this quite a few times when dealing with web
services and most recently, trying to pull a simple page with the
System.Net.WebClient object (in .Net 2.0).
The solution everybody comes up with is editing the .config
(web.config, app.config, machine.config, or whatever.config) and make
sure the following info is there:
<configuration>
<system.net>
<settings>
<httpWebRequest useUnsafeHeaderParsing="true" />
</settings>
</system.net>
</configuration>
This is a global setting, though. It's beyond my understanding as to
why MS didn't imaging the situation where a programmer might want to
toggle this in code. Perhaps intranet sites do not need the strict
security an external sites do.
There were a few posts that said it was possible to programmatically
alter the System.Configuration items to do all of this but I was never
able to find an example and I wasn't able to find any members of
System.Configuration that allowed for writing. It seemed to be a
"read-only" baby. (until .Net 2.0, but even now it doesn't look like
you can alter the same areas the http controls are looking.)
So I coded up something that probably isn't the most elegant solution,
but it gets the job done in what I was needing to do. Maybe somebody
else will find it useful. Or at least provide feedback on what might
be wrong with this.
It consists of creating a new app domain space with a custom config
file that does contain the needed setting.
I make no guarantees that the following code works. I know it worked
before I pasted it here into the browser, but I had to do a bunch of
formatting changes to get the word-wrapping to look good.
Function PullUrlToFile(ByVal url As String, ByVal filename As String)
As Integer
' set up a new app domain to read in a custom .config file
Dim config As String = "<configuration><system.net><settings>" _
"<httpWebRequest
useUnsafeHeaderParsing=""true""/>" _
"</settings></system.net></configuration>"
Dim tmpConfigFile As String = System.IO.Path.GetTempFileName
Unslurp(tmpConfigFile, config) ' function that dumps text to file
If (Not System.IO.File.Exists(tmpConfigFile)) Then _
Throw New System.IO.FileNotFoundException( _
"Unable to create custom configuration file.", tmpConfigFile)
Dim exeAssembly As String = Assembly.GetEntryAssembly.FullName
' Construct and initialize settings for a second AppDomain.
dim info as System.AppDomainSetup =
AppDomain.CurrentDomain.SetupInformation
Dim ads As New AppDomainSetup()
ads.ApplicationBase = info.ApplicationBase
ads.ApplicationName = info.ApplicationName
ads.ConfigurationFile = tmpConfigFile
Dim html As String = ""
Try
' Create the second Domain.
Dim ad2 As AppDomain = _
AppDomain.CreateDomain("DYNAMIC_CONFIG", Nothing, ads)
Try
Dim proxy As UrlSlurper = _
CType(ad2.CreateInstanceAndUnwrap(exeAssembly, _
GetType(UrlSlurper).FullName), UrlSlurper)
html = proxy.SlurpUrl(url)
Finally
' Unload the second AppDomain. This deletes its object and
' invalidates the proxy object.
AppDomain.Unload(ad2)
End Try
Catch ex As Exception
Console.WriteLine("Exception spawning secondary Domain")
Console.WriteLine("{0}", ex.Message)
If (ex.InnerException IsNot Nothing) Then
Console.WriteLine(ex.InnerException.Message)
End If
Return -5
End Try
' extra code deleted to ease the eyes
End Function
Public Class UrlSlurper
Inherits MarshalByRefObject
Public Function SlurpUrl(ByVal url As String) As String
Using www As New System.Net.WebClient
www.Headers.Add(Net.HttpRequestHeader.UserAgent, _
[String].Format("Mozilla/4.0 (compatible; MSIE 6.0; " + _
"Windows NT 5.2; .NET CLR {0}",
Environment.Version.ToString))
Console.WriteLine("Pulling: {0}", url)
Dim data As System.IO.Stream = www.OpenRead(url)
Try
Dim reader As New System.IO.StreamReader(data)
Try
Return reader.ReadToEnd()
Finally
reader.Close()
End Try
Finally
data.Close()
End Try
End Using
End Function
End Class
That's it. Hope it helps somebody.
-Joe