Describe the bug
When registering the refit client with the HttpClientFactoryExtensions using the method overload that takes in a runtime type (i.e. services.AddRefitClient(myInterfaceType, settings)), the service is not registered as it is with the generic version. This is due to it missing the line services.AddSingleton(provider => RequestBuilder.ForType(refitInterfaceType, settings)); similar to the way it does it in the first line of the generic method, located here.
Steps To Reproduce
IMyApiStartup.ConfigureServices, get a Type for your interface type and call the broken AddRefitClient method:var refitInterfaceType = typeof(IMyApi);
services.AddRefitClient(refitInterfaceType);
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private readonly IMyApi _api;
public ValuesController(IMyApi api)
{
_api = api;
}
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
_api.GetThing();
return new string[] { "value1", "value2" };
}
}
InvalidOperationException: Unable to resolve service for type 'IMyApi' while attempting to activate 'test_api.Controllers.ValuesController'.services.AddRefitClient<IMyApi>();Expected behavior
It is expected that adding the refit client with the runtime type will act the same as adding it with the generic type.
Environment
It looks like a bug.
https://github.com/reactiveui/refit/blob/master/Refit.HttpClientFactory/HttpClientFactoryExtensions.cs
You can do PR with tests.
GitHub
The automatic type-safe REST library for .NET Core, Xamarin and .NET. Heavily inspired by Square's Retrofit library, Refit turns your REST API into a live interface. - reactiveui/refit
I also got this problem.here is my solution.
```c#
public static IHttpClientBuilder AddTypedClient(this IHttpClientBuilder builder, Type type, Func
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (factory == null)
{
throw new ArgumentNullException(nameof(factory));
}
builder.Services.AddTransient(type, s =>
{
var httpClientFactory = s.GetRequiredService<IHttpClientFactory>();
var httpClient = httpClientFactory.CreateClient(builder.Name);
return factory(httpClient, s);
});
return builder;
}
2. Add a new AddRefitClient method
```c#
public static IHttpClientBuilder AddRefitClient(this IServiceCollection services, Type refitInterfaceType, RefitSettings settings = null)
{
return services.AddHttpClient(UniqueName.ForType(refitInterfaceType))
.AddTypedClient(refitInterfaceType, (client, serviceProvider) => RestService.For(refitInterfaceType, client, settings));
}
We had a similar problem, refit tried to register all the typeclient under the same name, so the DI container was throwing exception (this type is already registred...). We created this workaround :
public static class IServiceCollectionExtension
{
public static IServiceCollection AddRestServiceClient(this IServiceCollection services, Type type, Action<IServiceProvider, HttpClient> clientFactory)
{
services.AddHttpClient(type.FullName, clientFactory)
.Services.AddTransient(type, services =>
{
var httpClientFactory = services.GetRequiredService<IHttpClientFactory>();
var httpClient = httpClientFactory.CreateClient(type.FullName);
return Refit.RestService.For(type, httpClient);
});
return services;
}
public static IServiceCollection AddRestServiceClient(this IServiceCollection services, Type type, Action<HttpClient> clientFactory)
{
return AddRestServiceClient(services, type, (serviceProvider, client) => clientFactory(client));
}
}
I think the problem seem to be around the UniqueName.ForType
+1 me too.
is it released?
Closing due to age. Please try Refit v6 and reopen if still an issue.
Most helpful comment
We had a similar problem, refit tried to register all the typeclient under the same name, so the DI container was throwing exception (this type is already registred...). We created this workaround :
I think the problem seem to be around the
UniqueName.ForType