One of my biggest day to day problems is dealing with a corporate proxy. Especially with .Net Core 2 which is not completely configurable from the appsettings.json file yet. This post is about how to configure your application to handle it.

Configurable Proxy Settings

Firstly an application will not always be working behind a proxy so we need to make it configurable. In your appsettings.json file as in the following settings:

"MyConfig": {
    "UseProxy": "true",
    "ProxyHost": "127.0.0.1",
    "ProxyPort": "3128",
}

We then need a class for these settings to map to. Create the following MyConfig class:

public class MyConfig
{
    	public bool UseProxy { get; set; }
    	public string ProxyHost { get; set; }
    	public int ProxyPort { get; set; }
	}

Now we can configure our Startup.cs class to set up our configuration parameters as an injectable. In the ConfigureServices function add the following:

public void ConfigureServices(IServiceCollection services)
    {
	....
	// Add our Config object so it can be injected
        	services.Configure<MyConfig>(Configuration.GetSection("MyConfig"));
}

Now we can inject our configuration parameters where ever we need to, using the standard dependency injection style:

private readonly IOptions<MyConfig> _config;

    public HttpProxyClientService(IOptions<MyConfig> config)
    {
	_config = config;
    }

Create an Injectable Module

Following SOLID principals we will want to create a single point of reference for anything that will need to use the proxy. Two objects that are likely to use it are the HttpClient object and HttpWebRequest object. By designing it as a service you can add your own required objects down the line. For now, create the following interface:

public interface IHttpProxyClientService
{
    	HttpClient CreateHttpClient();
    	HttpWebRequest CreateHttpWebRequest(string requestUri);
 }

And then this boilerplate class for the next sections to come.

public class HttpProxyClientService : IHttpProxyClientService
	{
    	private readonly IOptions<MyConfig> _config;

    	public HttpProxyClientService(IOptions<MyConfig> config)
    	{
        		_config = config;
    	}

    	public HttpClient CreateHttpClient()
    	{
		return null;
    	}

    	public HttpWebRequest CreateHttpWebRequest(string requestUri)
    	{
		return null;
   		}
	}

Finally, register it in the Startup ConfigureServices function:

services.AddTransient<IHttpProxyClientService, HttpProxyClientService>();

We now have an injectable Service! Now let's sort out the functions.

HttpClient

The CreateHttpClient function is quite simple, if a proxy is required, configure it, otherwise, return a normal HttpClient object. We will pull the details from the configuration and if a proxy is required we will configure the returned HttpClient object to use a HttpClientHandler. The code is as follows:

public HttpClient CreateHttpClient()
    {
    	try
        	{
            	var useProxy = _config.Value.UseProxy;
            	if (!useProxy)
            	{
                		return new HttpClient();
            	}

            	var proxyHost = _config.Value.ProxyHost;
            	var proxyPort = _config.Value.ProxyPort.ToString();

            	var proxy = new WebProxy()
            	{
                		Address = new Uri("http://" + proxyHost + ":" + proxyPort),
                		UseDefaultCredentials = true
            	};

            	var httpClientHandler = new HttpClientHandler()
            	{
                		Proxy = proxy,
            	};

            	var client = new HttpClient(handler: httpClientHandler, disposeHandler: true);
            	return client;
        	}
        	catch (Exception ex)
        	{
            	Console.WriteLine("Error: " + ex.Message);
        	}

        	return null;
    }

Now instead of creating a HttpClient object when we need one, we just use the service instead.

var httpClient = _httpProxyClientService.reateHttpClient()

HttpWebRequest

It's probably no surprise that the HttpWebRequest will work in exactly the same way except the set up is a little different. Without going into to much detail, this is the code:

public HttpWebRequest CreateHttpWebRequest(string requestUri)
    {
    	try
        	{
            	var useProxy = _config.Value.UseProxy;
            	HttpWebRequest res = (HttpWebRequest)WebRequest.Create(requestUri);

            	if (!useProxy)
            	{
                		return res;
            	}

            	var proxyHost = _config.Value.ProxyHost;
            	var proxyPort = _config.Value.ProxyPort;
            	var myproxy = new WebProxy(proxyHost, proxyPort) { BypassProxyOnLocal = false };
            	res.Proxy = myproxy;
            
            	return res;
        	}
       	catch (Exception ex)
        	{
            	Console.WriteLine("Error: " + ex.Message);
        	}

        	return null;
    }

Conclusion

With that, you should now be able to handle Http requests through a proxy following SOLID principles. There's no direct code example for this one I'm afraid although I do use it in my Speech to Text API Comparator project if you'd like to see it in action. Cheers for reading.