Reputation: 4188
Trying to define an HttpClient singleton in StructureMap ala:
For<HttpClient>().Singleton().UseIfNone<HttpClient>();
This results in the following error in runtime (upon dependency injection):
StructureMap.StructureMapConfigurationException: No default Instance is registered and cannot be automatically determined for type 'System.Net.Http.HttpMessageHandler'
There is no configuration specified for System.Net.Http.HttpMessageHandler
1.) new HttpClient(*Default of HttpMessageHandler*)
2.) System.Net.Http.HttpClient
3.) Instance of System.Net.Http.HttpClient
4.) new AdmanAdapter(*Default of HttpClient*)
5.) Organotiki.vNext.PostEval.Data.Adapters.ADMAN.AdmanAdapter
6.) Instance of [....]
at lambda_method(Closure , IBuildSession , IContext )
at StructureMap.Building.BuildPlan.Build(IBuildSession session, IContext context)
at StructureMap.BuildSession.BuildNewInSession(Type pluginType, Instance instance)
at StructureMap.Pipeline.NulloTransientCache.Get(Type pluginType, Instance instance, IBuildSession session)
at StructureMap.BuildSession.ResolveFromLifecycle(Type pluginType, Instance instance)
at StructureMap.SessionCache.GetObject(Type pluginType, Instance instance, ILifecycle lifecycle)
If we also configure HttpMessageHandler like so:
For<HttpClient>().Singleton().UseIfNone<HttpClient>();
For<HttpMessageHandler>().UseIfNone(x => new HttpClientHandler());
Then the problem goes away. The question is why? The default constructor for HttpClient takes care of its own dependency injection:
/// <summary>Initializes a new instance of the <see cref="T:System.Net.Http.HttpClient" /> class.</summary>
[__DynamicallyInvokable]
public HttpClient()
: this((HttpMessageHandler) new HttpClientHandler())
{
}
Am I missing something here?
Upvotes: 1
Views: 1709
Reputation: 240
This is how I made it work:
For<HttpMessageHandler>().UseIfNone(x => new HttpClientHandler());
var recaptchaHttpClient = new HttpClient
{
BaseAddress = new Uri("https://www.recaptcha.net/recaptcha/")
};
For<IReCaptchaService>().Use<ReCaptchaService>()
.SelectConstructor(() => new ReCaptchaService(recaptchaHttpClient));
Upvotes: 0
Reputation: 1751
Extending @Brad M's answer, what worked for me is .SelectConstructor(() => new HttpClient())
. Specifying which constructor should be used explicitly.
Upvotes: 1
Reputation: 7898
From structuremap docs at http://structuremap.github.io/registration/constructor-selection
If there are multiple public constructor functions on a concrete class, StructureMap's default behavior is to select the "greediest" constructor, i.e., the constructor function with the most parameters.
If you look at the possible constructors for HttpClient
, it should be
public HttpClient();
public HttpClient(HttpMessageHandler handler);
public HttpClient(HttpMessageHandler handler, bool disposeHandler);
Upvotes: 2