Fix: ILogger Type Mismatch in AdapterWithErrorHandler CloudAdapter
When creating an AdapterWithErrorHandler
class that inherits from CloudAdapter
, you might encounter this compile error:
Argument 3: cannot convert from 'Microsoft.Extensions.Logging.ILogger<Microsoft.Agents.Hosting.AspNetCore.IAgentHttpAdapter>' to 'Microsoft.Extensions.Logging.ILogger<Microsoft.Agents.Hosting.AspNetCore.CloudAdapter>'
This happens because you're passing ILogger<IAgentHttpAdapter>
to the CloudAdapter
base constructor, but it expects ILogger<CloudAdapter>
.
The Problem Code
Here's the AdapterWithErrorHandler
code that causes the compile error:
public class AdapterWithErrorHandler : CloudAdapter
{
public AdapterWithErrorHandler(IChannelServiceClientFactory channelServiceClientFactory, IActivityTaskQueue activityTaskQueue, ILogger<IAgentHttpAdapter> logger)
: base(channelServiceClientFactory, activityTaskQueue, logger: logger)
{
OnTurnError = async (turnContext, exception) =>
{
// Log any leaked exception from the application.
// NOTE: In production environment, you should consider logging this to
// Azure Application Insights. Visit https://aka.ms/bottelemetry to see how
// to add telemetry capture to your bot.
logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");
// Only send error message for user messages, not for other message types so the bot doesn't spam a channel or chat.
if (turnContext.Activity.Type == ActivityTypes.Message)
{
// Send a message to the user
await turnContext.SendActivityAsync($"The bot encountered an unhandled error: {exception.Message}");
await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code.");
// Send a trace activity
await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError");
}
};
}
}
The issue is on line 3: ILogger<IAgentHttpAdapter> logger
and passing it to the base constructor. The CloudAdapter
expects ILogger<CloudAdapter>
, not ILogger<IAgentHttpAdapter>
.
Solution: Change Logger Type to CloudAdapter
Update your constructor to accept ILogger<CloudAdapter>
instead:
public class AdapterWithErrorHandler : CloudAdapter
{
public AdapterWithErrorHandler(IChannelServiceClientFactory channelServiceClientFactory, IActivityTaskQueue activityTaskQueue, ILogger<CloudAdapter> logger)
: base(channelServiceClientFactory, activityTaskQueue, logger: logger)
{
OnTurnError = async (turnContext, exception) =>
{
logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");
if (turnContext.Activity.Type == ActivityTypes.Message)
{
await turnContext.SendActivityAsync($"The bot encountered an unhandled error: {exception.Message}");
await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code.");
await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError");
}
};
}
}
What changed:
- Constructor parameter:
ILogger<IAgentHttpAdapter>
→ILogger<CloudAdapter>
- Now the logger type matches what
CloudAdapter
expects
Why This Happens
The CloudAdapter
base class constructor signature expects:
CloudAdapter(..., ILogger<CloudAdapter> logger)
But your code was passing:
ILogger<IAgentHttpAdapter> logger
In .NET, ILogger<T>
types are not interchangeable even if the classes are related. ILogger<CloudAdapter>
and ILogger<IAgentHttpAdapter>
are completely different types.
Summary
Change your constructor parameter to ILogger<CloudAdapter>
and pass it to the base constructor. This aligns your adapter's logging category with the actual implementation class.
The .NET dependency injection container automatically provides ILogger<T>
for any type T
, so no additional registration is needed.