I ran into a situation with the following network topology:
The intranet server served PDF documents via IIS, but was only accessible from the WCF server - which, for technical and political reasons, could not run in IIS but had to be a Windows Managed service that hosted a WCF service. Yet I needed to be able to download files from the intranet server via an ordinary URL.
It turns out that you can write a WCF service mimicking a HTTP server pretty easily. If you can utilize .NET 3.5SP1, that is.
1. Data contract
There are few key points to the contract:
Your datacontract could look like this:
- Make a reference to System.ServiceModel.Web.dll
- Add a "using System.ServiceModel.Web"
- Define a method returning a Stream
- Decorate that method with a WebGet attribute
/// Service contract for a proxy that forwards a http request
public interface IHttpProxy
Stream GetProxyRequest(string target);
}2. Implementation class
This is basically a modified version of a solution based upon an ASP.NET page I described before.
/// A proxy that forwards a http request
public class HttpProxy : IHttpProxy
public Stream GetProxyRequest(string target)
var urlToLoadFrom = HttpUtility.UrlDecode(target);
HttpWebRequest webRequest =
HttpWebRequest.Create(urlToLoadFrom) as HttpWebRequest;
// Important! Keeps the request from blocking after the first
webRequest.KeepAlive = false;
webRequest.Credentials = CredentialCache.DefaultCredentials;
using (var backendResponse =
using (var receiveStream =
var ms = new MemoryStream();
var response =
// Copy headers
// Check if header contains a contenth-lenght since IE
// goes bananas if this is missing
bool contentLenghtFound = false;
foreach (string header in backendResponse.Headers)
"CONTENT-LENGTH", true) == 0)
contentLenghtFound = true;
// Copy contents
var buff = new byte;
var length = 0;
while ((bytes = receiveStream.Read(buff, 0, 1024)) > 0)
length += bytes;
ms.Write(buff, 0, bytes);
// Add contentlength if it is missing
if (!contentLenghtFound) response.ContentLength = length;
// Set the stream to the start
ms.Position = 0;
}3. Configuration settings
To get it all to work, you will need some configuration settings in the App.config of the hosting application:
<service name="ProxyService.HttpProxy" >
<endpoint address="" binding="webHttpBinding"
<add baseAddress="http://localhost:8002/ProxyService.HttpProxy" />
</system.serviceModel>Notice the endpointBehaviors section: this is really important to get the stuff to work.
4. Using the proxy
You can now simply enter "http://yourhost:8002/ProxyService.HttpProxy/GetProxyRequest?target=urlencodedurl" in your browser, and the WebGet attributes will automatically make the GetProxyRequest method get called with the value of target as value for the target parameter. The code of the proxy expects target to contain an URLEncoded URL (use HttpUtility.UrlEncode to encode the actual url to something that can be passed as a parameter on an URL).
The magic of the WebGet attribute is barely scratched by this example, but it makes creating REST services with WCF a real piece of cake. I am not sure if it was intended to be used this way, but it sure works like hell ;-)