Skip to content

Commit d8aadb1

Browse files
Improve error message for TypedHttpClient missing constructor parameter (#108670)
* Improve error message for TypedHttpClient missing constructor parameter * Address code review comments * Update src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/DependencyInjection/HttpClientFactoryServiceCollectionExtensionsTest.cs --------- Co-authored-by: Natalia Kondratyeva <knatalia@microsoft.com>
1 parent 07e9313 commit d8aadb1

3 files changed

Lines changed: 43 additions & 1 deletion

File tree

src/libraries/Microsoft.Extensions.Http/src/DefaultTypedHttpClientFactory.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,17 @@ public TClient CreateClient(HttpClient httpClient)
3535
// as a transient, so that it doesn't close over the application root service provider.
3636
public sealed class Cache
3737
{
38-
private static readonly Func<ObjectFactory> _createActivator = () => ActivatorUtilities.CreateFactory(typeof(TClient), new Type[] { typeof(HttpClient), });
38+
private static readonly Func<ObjectFactory> _createActivator = () =>
39+
{
40+
try
41+
{
42+
return ActivatorUtilities.CreateFactory(typeof(TClient), new Type[] { typeof(HttpClient), });
43+
}
44+
catch (InvalidOperationException iox)
45+
{
46+
throw new InvalidOperationException(SR.Format(SR.TypedClient_NoHttpClientCtor, typeof(TClient).Name), iox);
47+
}
48+
};
3949

4050
private ObjectFactory? _activator;
4151
private bool _initialized;

src/libraries/Microsoft.Extensions.Http/src/Resources/Strings.resx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,4 +141,8 @@
141141
2 = Environment.NewLine
142142
3 = handler.ToString()</comment>
143143
</data>
144+
<data name="TypedClient_NoHttpClientCtor" xml:space="preserve">
145+
<value>A suitable constructor for type '{0}' could not be located. A Typed client must provide a constructor taking a 'System.Net.Http.HttpClient' as a parameter.</value>
146+
<comment>{0} = instance type</comment>
147+
</data>
144148
</root>

src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/DependencyInjection/HttpClientFactoryServiceCollectionExtensionsTest.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,22 @@ public void AddHttpClient_AddSameTypedClientTwice_WithDifferentNames_WithAddType
602602
Assert.Equal(2, clients.Count());
603603
}
604604

605+
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
606+
public void AddHttpClient_TypedClient_NoHttpClientCtor_ThrowsSpecificException()
607+
{
608+
// Arrange
609+
var serviceCollection = new ServiceCollection();
610+
serviceCollection.AddHttpClient<TypedClientNoHttpClientCtor>();
611+
612+
var services = serviceCollection.BuildServiceProvider();
613+
614+
// Act
615+
var ex = Assert.Throws<InvalidOperationException>(() => services.GetRequiredService<TypedClientNoHttpClientCtor>());
616+
Assert.Equal(
617+
SR.Format(SR.TypedClient_NoHttpClientCtor, typeof(TypedClientNoHttpClientCtor).Name),
618+
ex.Message);
619+
}
620+
605621
[Fact]
606622
public void AddHttpClient_AddSameNameWithTypedClientTwice_ThrowsError()
607623
{
@@ -1573,6 +1589,18 @@ public TypedClientWithTransientService(HttpClient httpClient, TransientService s
15731589

15741590
public TransientService Service { get; }
15751591
}
1592+
1593+
// Simple typed client but the HttpClient parameter is missing
1594+
private class TypedClientNoHttpClientCtor
1595+
{
1596+
// This is an error case - do not use Typed clients like this!
1597+
public TypedClientNoHttpClientCtor(IHttpClientFactory httpClientFactory)
1598+
{
1599+
HttpClientFactory = httpClientFactory;
1600+
}
1601+
1602+
public IHttpClientFactory HttpClientFactory { get; }
1603+
}
15761604
}
15771605
}
15781606

0 commit comments

Comments
 (0)