Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use HttpClient in asp.net webforms

I've spent quite a bit of time researching, but yet to find a reliable answer, so I'd like to start a fresh, new question.

What is the guidance for using the HttpClient class in an ASP.NET webforms based website? Note, this is not an MVC site, it's not .NET Core anything. It's an ASP.NET Webforms website. It is on the latest .NET Framework (4.8).

The technical challenge seems to be surrounding all the "you're doing it wrong" with HttpClient that leads to socket exhaustion. So the advice is to use dependency injection (presuming you're doing a .net core web app) or static instance (usually noted for console apps). But would you really declare a static variable for a webforms site (in App_Code or Global.asax)?

It seems incredible that to make use of any kind of REST API's, which is common, is so difficult to "get right."

The other challenge is that all its methods are async. However, I think that's doable after reading enough posts (and SO answers) from Stephen Cleary.

My main concern here, with HttpClient specifically, is it's proper usage (lifetime management, avoiding the socket exhaustion issue and also stale DNS issue with a "long lived" instance) in a webforms based website.

like image 682
Margo Noreen Avatar asked Sep 24 '20 16:09

Margo Noreen


2 Answers

Quite simple really. Ignore the IDisposable interface it implements and create a single point/object like ExampleApiClient, from where you'll call it.

Declare your member as:

private static readonly HttpClient client = new HttpClient();

And encapsulate its use by using it in a public function.

There is a reason to create a new client though. If for example you want to call multiple different apis, with different proxies or default headers, create one for each api, but certainly not one for each request.

like image 197
Athanasios Kataras Avatar answered Sep 19 '22 14:09

Athanasios Kataras


The way to avoid socket exhaustion and the DNS issues you mention is to use the HttpClientFactory which manages client creation for you. It is described here in the Microsoft docs.

Here is some code which shows you how it can be used in a webforms app, assuming you are targeting the .NET framework version 4.7.2 or above which in your case is true. The basic idea is to new up a ServiceCollection and configure it give you an httpClientfactory. Then build it and use it to give you and httpClientfactory.

First install the nuget package Microsoft.Extensions.Http. Then add a reference to System.Net.Http.

using Microsoft.Extensions.DependencyInjection;
using System;
using System.Net.Http;

namespace HttpClientExample
{
    public static class HttpClientFactoryProvider
    {
        private static IHttpClientFactory _httpClientFactory;
        private const string _ClientKey = "DotNetClientKey";

        private static IHttpClientFactory GetHttpClientFactory()
        {
            if (_httpClientFactory != null)
            {
                return _httpClientFactory;
            }
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddHttpClient(_ClientKey);
            var serviceProvider = serviceCollection.BuildServiceProvider();
            _httpClientFactory = serviceProvider.GetService<IHttpClientFactory>();
            return _httpClientFactory;
        } 

        public static HttpClient GetClient()
        {
            return GetHttpClientFactory().CreateClient(_ClientKey);
        }
    }
 
    //here's an example of how a webform can accesses the httpclient through the above code
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {    
            var client = HttpClientFactoryProvider.GetClient();
            //rest of code that uses the client
        }
    }
}

This is a simple example but you can configure things to do what you want just like you can in a dotnet core app. Again this is explained in here Microsoft docs.

like image 26
Dave Barnett Avatar answered Sep 17 '22 14:09

Dave Barnett