unchase/Unchase.OpenAPI.Connectedservice

[BUG] Switching off Inject HttpClient via constructor resulting in error prone code

Closed this issue · 0 comments

Describe the bug

I have generated a c# client of an existing open API specification and played around with the option Inject HttpClient via constructor. In my opinion the resulting client is not sophisticated and error prone because for every request a new HttpClient will be created with a new HttpClientHandler. In .net core the build in pooled connection should be used instead via the IHttpClientFactory interface. (see Guidelines for using HttpClient)

Assemblies affected

Connected Service version: v 1.9.1.0
NSwag command version: v 13.19.0.0

Steps to reproduce

  1. Configure Specification endpoint in Visual Studio 2022
  2. Fill in an open API specification URl path
  3. Select Generate CSharp client
  4. Click Next
  5. Unselect Inject HttpClient via constructor
  6. Click Finish

Expected result

public partial class GeneratedClient
{
	private readonly System.Lazy<Newtonsoft.Json.JsonSerializerSettings> _settings;
	protected readonly IHttpClientFactory _httpClientFactory;

	public GeneratedClient(System.Net.Http.IHttpClientFactory httpClientFactory)
	{
		_settings = new System.Lazy<Newtonsoft.Json.JsonSerializerSettings>(CreateSerializerSettings);
		_httpClientFactory = httpClientFactory;
	}

	private Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings()
	{
		var settings = new Newtonsoft.Json.JsonSerializerSettings();
		UpdateJsonSerializerSettings(settings);
		return settings;
	}

	partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings);
   
	partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url);
	
	partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder);
	
	partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response);
	
	protected virtual HttpClient CreateHttpClient()
	{
		return _httpClientFactory.CreateClient(GetType().FullName!);
	}

	public virtual async System.Threading.Tasks.Task JustATestAsync(System.Threading.CancellationToken cancellationToken)
	{
		var urlBuilder_ = new System.Text.StringBuilder();
		urlBuilder_.Append("api/v1/just-a-test");

		var client_ = CreateHttpClient();
		var disposeClient_ = true;
		try
		{
			using (var request_ = new System.Net.Http.HttpRequestMessage())
			{
				// ...
				await Task.CompletedTask.ConfigureAwait(false);
			}
		}
		finally
		{
			if (disposeClient_)
				client_.Dispose();
		}
	}
}

Actual result

public partial class GeneratedClient
{
	private readonly System.Lazy<Newtonsoft.Json.JsonSerializerSettings> _settings;

	public GeneratedClient()
	{
		_settings = new System.Lazy<Newtonsoft.Json.JsonSerializerSettings>(CreateSerializerSettings);
	}

	private Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings()
	{
		var settings = new Newtonsoft.Json.JsonSerializerSettings();
		UpdateJsonSerializerSettings(settings);
		return settings;
	}

	partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings);
   
	partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url);
	
	partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder);
	
	partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response);
	
	public virtual async System.Threading.Tasks.Task JustATestAsync(System.Threading.CancellationToken cancellationToken)
	{
		var urlBuilder_ = new System.Text.StringBuilder();
		urlBuilder_.Append("api/v1/just-a-test");

		var client_ = new System.Net.Http.HttpClient(); // <<--- please don't do this
		var disposeClient_ = true;
		try
		{
			using (var request_ = new System.Net.Http.HttpRequestMessage())
			{
				// ...
				await Task.CompletedTask.ConfigureAwait(false);
			}
		}
		finally
		{
			if (disposeClient_)
				client_.Dispose();
		}
	}
}

Screenshots

image