Discord.Net Received Message Content always Empty - c#

I'm trying to make A Discord bot but all Messages that the Bot receives are empty for some reason.
I guess it has something to do with the permissions in Discord (cause the slash commands are also not working) but I just can't figure it out.
I added the bot to my Discord Sever with Admin permissions. The code should be right cause I already programemd a bot a Year ago (which worked and still works) and only copied it but neverless here's my code (summarised cause there's more stuff thats irrelevant to this problem):
public async Task StartAsync()
{
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("config.json", false, true)
.Build();
using IHost host = Host.CreateDefaultBuilder()
.ConfigureServices((_, services) => services
.AddSingleton(config)
.AddSingleton(x => new DiscordSocketClient(new DiscordSocketConfig
{
GatewayIntents = GatewayIntents.AllUnprivileged,
AlwaysDownloadUsers = true,
}))
.AddSingleton(x => new InteractionService(x.GetRequiredService<DiscordSocketClient>()))
.AddSingleton<InteractionHandler>()
.AddSingleton(x => new CommandService(new CommandServiceConfig
{
LogLevel = LogSeverity.Debug,
DefaultRunMode = Discord.Commands.RunMode.Async
}))
.AddSingleton<PrefixHandler>())
.Build();
await RunAsync(host);
}
public async Task RunAsync(IHost host)
{
using IServiceScope servicScope = host.Services.CreateScope();
IServiceProvider provider = servicScope.ServiceProvider;
var sCommands = provider.GetRequiredService<InteractionService>();
_client = provider.GetRequiredService<DiscordSocketClient>();
var config = provider.GetRequiredService<IConfigurationRoot>();
await provider.GetRequiredService<InteractionHandler>().InitializeAsync(); //For Slash commands
var pCommands = provider.GetRequiredService<PrefixHandler>();
pCommands.AddModule<PrefixModule>();
await pCommands.InitializeAsync();
_client.Ready += async () =>
{
await sCommands.RegisterCommandsToGuildAsync(UInt64.Parse(config["testGuild"]));
};
await _client.LoginAsync(TokenType.Bot, config["token"]);
await _client.StartAsync();
await Task.Delay(-1);
}
And here the PrefixHandler that Handles normal Commands:
internal sealed class PrefixHandler
{
readonly DiscordSocketClient _client;
readonly CommandService _commands;
readonly IConfigurationRoot _config;
public PrefixHandler(DiscordSocketClient client, CommandService commands, IConfigurationRoot config)
{
_client = client;
_commands = commands;
_config = config;
}
public async Task InitializeAsync()
{
_client.MessageReceived += HandleCommandAsync;
}
public void AddModule<T>()
{
_commands.AddModuleAsync<T>(null);
}
async Task HandleCommandAsync(SocketMessage messageParam)
{
Console.WriteLine("Message: '" + messageParam.Content + "'"); //Always Prints Empty ''
}
}
If I forgot anything or if I should add something feel free to let me know, so I can add it. I hope the problem gets resolved and Thanks in advance

If you haven't already, enable "Message Content Intent" in the Discord developer portal and add the MessageContent intent to the GatewayIntents property in your DiscordSocketClient constructor.
GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.MessageContent

Related

Xamarin Restart HttpClientFactory

In my Xamarin app I get an exception on app startup on both Android and iOS.
"Cannot access a disposed object. Object name: 'MobileAuthenticatedStream'"
This seems to be happening after a background fetch has been run.
I am initializing my httpclientfactory like so
static void Init()
{
var host = new HostBuilder()
.ConfigureHostConfiguration(c =>
{
c.AddCommandLine(new string[] { $"ContentRoot={FileSystem.AppDataDirectory}" });
})
.ConfigureServices((c, x) =>
{
ConfigureServices(c, x);
})
.Build();
ServiceProvider = host.Services;
}
static void ConfigureServices(HostBuilderContext ctx, IServiceCollection services)
{
services.AddSingleton<Helpers.ClientService>();
services.AddHttpClient("webClient", client =>
{
client.DefaultRequestHeaders.Authorization = GenerateAuthHeader();
})
.AddPolicyHandler(GetRetryPolicy());
}
Then getting the client for use like
public class ClientService
{
IHttpClientFactory _httpClientFactory;
public ClientService(IHttpClientFactory factory)
{
_httpClientFactory = factory;
}
public HttpClient GetClient()
{
return _httpClientFactory.CreateClient(App.ClientName);
}
}
Helpers.ClientService service = App.ServiceProvider.GetService<Helpers.ClientService>();
HttpClient client = service.GetClient();
HttpResponseMessage response = await client.GetAsync(url);
On app start and resume I am re-running Init method.
Is this re-initializing the factory correctly, if not how should I implement this functionality

IHost not returning when Task completed

I'm writing a Windows Service (using .NET Core 3.1), using a BackgroundService and I seem to have an issue when I want to programmatically stop the service.
My main function is as follows
static async Task Main(string[] args)
{
IHost host = null;
try
{
host = CreateService(args).Build();
await host.RunAsync();
Console.WriteLine("Ending");
}
catch (Exception ex)
{
Console.WriteLine("Exception");
}
finally
{
if (host is IAsyncDisposable d) await d.DisposeAsync();
}
}
public static IHostBuilder CreateService(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService(options =>
{
options.ServiceName = "My Service";
})
.ConfigureServices((hostContext, services) =>
{
IConfiguration configuration = hostContext.Configuration;
ServiceOptions options = configuration.GetSection("ServiceOptions").Get<ServiceOptions>();
WorkerService sService = new WorkerService();
services.AddSingleton(options);
services.AddSingleton(sService);
services.AddHostedService<WindowsBackgroundService>(service => new WindowsBackgroundService(
service.GetService<WorkerService>(),
service.GetService<ILogger<WindowsBackgroundService>>(),
service.GetService<ServerOptions>()
));
});
The background service is as follows:
public sealed class WindowsBackgroundService : BackgroundService
{
private WorkerService _workerService;
private ServerOptions _options;
private ILogger<WindowsBackgroundService> _logger;
public WindowsBackgroundService(
WorkerService workerService, ILogger<WindowsBackgroundService> logger,
ServiceOptions serviceOptions) => (_workerService, _logger, _options) = (workerService, logger, serviceOptions);
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
bool allDone = false;
while (!stoppingToken.IsCancellationRequested && !allDone)
{
await Task.Delay(TimeSpan.FromSeconds(15), stoppingToken);
// Log to watchdog
// Check if we are in the run window
if (_options.InActivePeriod())
{
Console.WriteLine("Process Queue");
var processResult = _workerService.Process(_options);
if (!processResult && _workerService.FatalError)
{
_workerService = null;
allDone = true;
Console.WriteLine("Service Quitting");
}
}
}
Console.WriteLine($"Task Ending {stoppingToken.IsCancellationRequested}");
return;
}
}
}
So everything runs as it should and I run this under the debugger or from the command line (I haven't actually installed it as a Windows Service yet as I'm still writing the code).
The function Process executes correctly. If it encounters an error that cannot be recovered, it sets it's FatalError property that is supposed to be a signal that the whole service should be stopped. The Task does indeed complete (the correct lines are written to console) but the line Console.WriteLine("Ending"); is never executed. It looks like the host.RunAsync(); never returns (unless I do a CTRL+C).
I'm not entirely certain what I am doing wrong at this point. Can anyone point me in the write direction?
Based on the shown code I see nothing that would cause the host to stop.
The hosted service, once started has no bearing on the application host itself. So even when ExecuteAsync is completed, the completion of that function does not mean that the host will stop running.
You could consider injecting IHostApplicationLifetime into the hosted service and explicitly telling the application to stop programmatically;
For example
public sealed class WindowsBackgroundService : BackgroundService {
private WorkerService _workerService;
private ServerOptions _options;
private ILogger<WindowsBackgroundService> _logger;
private IHostApplicationLifetime lifetime;
public WindowsBackgroundService(
WorkerService workerService, ILogger<WindowsBackgroundService> logger,
ServiceOptions serviceOptions, IHostApplicationLifetime lifetime)
=> (_workerService, _logger, _options, this.lifetime) = (workerService, logger, serviceOptions, lifetime);
protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
bool allDone = false;
while (!stoppingToken.IsCancellationRequested && !allDone) {
await Task.Delay(TimeSpan.FromSeconds(15), stoppingToken);
// Log to watchdog
// Check if we are in the run window
if (_options.InActivePeriod()) {
Console.WriteLine("Process Queue");
var processResult = _workerService.Process(_options);
if (!processResult && _workerService.FatalError) {
_workerService = null;
allDone = true;
Console.WriteLine("Service Quitting");
lifetime.StopApplication(); //SIGNAL APPLICATION TO STOP
}
}
}
Console.WriteLine($"Task Ending {stoppingToken.IsCancellationRequested}");
return;
}
}
I am also curious about how you configured your services. Why use the factory delegate when everything you resolved manually would have been injected automatically if the default registration was done?
//...
.ConfigureServices((hostContext, services) => {
IConfiguration configuration = hostContext.Configuration;
ServiceOptions options = configuration.GetSection("ServiceOptions").Get<ServiceOptions>();
services.AddSingleton(options);
services.AddSingleton<WorkerService>();
services.AddHostedService<WindowsBackgroundService>();
});
The logging and and host lifetime are added for you by the Host.CreateDefaultBuilder

How to implement Dependency Injection in .Net core Console Application

I have a project .Net Core in React and, to save time, I would like to test a method to export files by a Console Application. But I can't to implement the DI in my console, here's the error:
Unable to resolve service for type 'Microsoft.Extensions.Logging.ILogger`1[MyPrj.Managers.Managers.Implementations.MyLogManager]' while attempting to activate 'MyPrj.Managers.Managers.Implementations.MyLogManager'.
This is a simplified version of my Program.cs:
class Program
{
public static IConfigurationRoot Configuration;
public static ServiceProvider serviceProvider;
public static void Main(string[] args)
{
var services = new ServiceCollection();
var builder = new ConfigurationBuilder()
.SetBasePath(Path.Combine(AppContext.BaseDirectory))
.AddJsonFile("appsettings.json", optional: true);
Configuration = builder.Build();
services.AddDbContext<MyDBContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.Configure<MailOptions>(Configuration.GetSection("EmailSettings"));
[... other options...]
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<ILogManager, MyLogManager>();
services.AddScoped<IMailManager, MailManager>();
[... other services ...]
services.AddScoped<IDocumentationManager, DocumentationManager>();
serviceProvider = services.BuildServiceProvider();
MainAsync().GetAwaiter().GetResult();
Console.WriteLine("END");
Console.ReadKey();
}
private static async Task MainAsync()
{
await ExportAsync();
}
public static async Task ExportAsync()
{
using (MyDBContext dbContext = serviceProvider.GetService<MyDBContext>())
{
List<User> user = dbContext.Users.ToList();
var logger = serviceProvider.GetService<ILogManager>();
var docManager = serviceProvider.GetService<IDocumentationManager>();
string userAnswer = Console.ReadLine();
var file = await docManager.GetUser(userAnswer);
File.WriteAllBytes("C:\tmp\user.txt", file.File);
}
}
}
Since you are creating your console app from scratch you have to manually configure the logger, otherwise it would not be injected.
var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole()
.AddEventLog();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Example log message");
services.AddSingleton<ILoggerFactory>(loggerFactory);
public class MyLogManager : ILogManager {
private readonly ILogger<MyLogManager> logger;
public MyLogManager(ILoggerFactory factory) {
logger = factory.CreateLogger<MyLogManager>();
}
}
you can find more here https://learn.microsoft.com/aspnet/core/fundamentals/logging/?view=aspnetcore-3.1
You can use a HostedService for encapsulating the StartAsync and StopAsync, making the code more elegancy.
public class HostedService : IHostedService
{
private readonly ISolrSeeder _seeder;
public HostedService(ISolrSeeder seeder)
{
_seeder = seeder;
}
public async Task StartAsync(CancellationToken cancellationToken)
=> await _seeder.SeedAsync(cancellationToken);
public async Task StopAsync(CancellationToken cancellationToken) =>
await Task.Run(() => Environment.Exit(Environment.ExitCode), cancellationToken);
}
And then, you can make your program.cs represents the startup from a console application, considering many environments.
internal class Program
{
private const string SettingsName = "appsettings";
private const string SettingsExtention = ".json";
private const string AppSettings = SettingsName + SettingsExtention;
public static async Task Main(string[] args)
=> await new HostBuilder()
.ConfigureHostConfiguration(configHost =>
{
configHost
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile(AppSettings, true, true)
.AddEnvironmentVariables()
.AddCommandLine(args);
})
.ConfigureAppConfiguration((hostContext, configApp) =>
{
configApp
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile(AppSettings, true, true)
.AddJsonFile(SettingsName + "." + hostContext.HostingEnvironment.EnvironmentName + SettingsExtention, true, true)
.AddEnvironmentVariables()
.AddCommandLine(args);
})
.ConfigureServices((hostContext, services) =>
{
services
.AddLogging()
.AddRepositories()
.AddDbContext(options => options.ConnectionString = hostContext.Configuration.GetConnectionString("DefaultConnection"))
.AddSolr(options =>
{
options.BaseAddress = hostContext.Configuration["Solr:BaseAddress"];
options.Core = hostContext.Configuration["Solr:Core"];
})
.AddScoped<ISolrSeeder, SolrSeeder>()
.AddHostedService<HostedService>();
})
.ConfigureLogging((hostContext, configLogging) =>
{
configLogging.AddConsole();
})
.UseConsoleLifetime()
.Build()
.RunAsync();
}
The rest of the code is available on this repository.
Thanks to all,
it has been enough adding services.AddLogging(), following #Steven 's advice, to solve my problem.

Performing a health check in .NET Core Worker Service

How can I implement health checks in a .NET Core Worker Service?
The service will be run inside Docker and needs to be able to check the health of the service.
Another way of doing this is to implement IHealthCheckPublisher.
The benefits of this approach is the ability to re-use your existing IHealthChecks or integration with 3rd party libraries that rely on IHealthCheck interface (like this one).
Though you still target Microsoft.NET.Sdk.Web as the SDK you don't need to add any asp.net specifics.
Here is an example:
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host
.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services
.AddHealthChecks()
.AddCheck<RedisHealthCheck>("redis_health_check")
.AddCheck<RfaHealthCheck>("rfa_health_check");
services.AddSingleton<IHealthCheckPublisher, HealthCheckPublisher>();
services.Configure<HealthCheckPublisherOptions>(options =>
{
options.Delay = TimeSpan.FromSeconds(5);
options.Period = TimeSpan.FromSeconds(5);
});
});
}
public class HealthCheckPublisher : IHealthCheckPublisher
{
private readonly string _fileName;
private HealthStatus _prevStatus = HealthStatus.Unhealthy;
public HealthCheckPublisher()
{
_fileName = Environment.GetEnvironmentVariable(EnvVariableNames.DOCKER_HEALTHCHECK_FILEPATH) ??
Path.GetTempFileName();
}
public Task PublishAsync(HealthReport report, CancellationToken cancellationToken)
{
// AWS will check if the file exists inside of the container with the command
// test -f $DOCKER_HEALTH_CHECK_FILEPATH
var fileExists = _prevStatus == HealthStatus.Healthy;
if (report.Status == HealthStatus.Healthy)
{
if (!fileExists)
{
using var _ = File.Create(_fileName);
}
}
else if (fileExists)
{
File.Delete(_fileName);
}
_prevStatus = report.Status;
return Task.CompletedTask;
}
}
I don't think is worth it to change SDK to Microsoft.NET.Sdk.Web. You will include additional middlewares just because of one health check? No thanks ...
What you could do is to use a different protocol like TCP.
The general idea is:
Create a separate background service that creates a TCP server (take a look at TcpListener.cs)
When you receive a request you have two options: if the application is healthy accept TCP connection otherwise reject it.
If you use containers your orchestrator should have an option to call it over TCP (in k8s there is a property tcpSocket)
If you need more detailed information you may check: Monitoring Health of ASP.NET Core Background Services With TCP Probes on Kubernetes
Cheers!
I think that you should also consider to retain the Microsoft.NET.Sdk.Worker.
Don't change the whole sdk just because of the health checks.
Then you can create a backgroundservice (just like the main worker), in order to update a file to write for example the current timestamp. An example of the background health check worker would be:
public class HealthCheckWorker : BackgroundService
{
private readonly int _intervalSec;
private readonly string _healthCheckFileName;
public HealthCheckWorker(string healthCheckFileName, int intervalSec)
{
this._intervalSec = intervalSec;
this._healthCheckFileName = healthCheckFileName;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (true)
{
File.WriteAllText(this._healthCheckFileName, DateTime.UtcNow.ToString());
await Task.Delay(this._intervalSec * 1000, stoppingToken);
}
}
}
Then you can add a extension method like this:
public static class HealthCheckWorkerExtensions
{
public static void AddHealthCheck(this IServiceCollection services,
string healthCheckFileName, int intervalSec)
{
services.AddHostedService<HealthCheckWorker>(x => new HealthCheckWorker(healthCheckFileName, intervalSec));
}
}
With this you can add in services the health check support
.ConfigureServices(services =>
{
services.AddHealthCheck("hc.txt", 5);
})
Add HTTPListener and expose the health checks endpoints.
Using HTTPListener does not require adding Microsoft.NET.Sdk.Web SDK.
Program.cs
using Consumer;
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
services.AddHostedService<HttpHealthcheck>();
})
.Build();
await host.RunAsync();
HttpHealthcheck.cs
using System.Net;
using System.Text;
namespace Consumer;
public class HttpHealthcheck : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly HttpListener _httpListener;
private readonly IConfiguration _configuration;
public HealthcheckHttpListener(ILogger<Worker> logger, IConfiguration configuration)
{
_logger = logger;
_configuration = configuration;
_httpListener = new HttpListener();
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_httpListener.Prefixes.Add($"http://*:5001/healthz/live/");
_httpListener.Prefixes.Add($"http://*:5001/healthz/ready/");
_httpListener.Start();
_logger.LogInformation($"Healthcheck listening...");
while (!stoppingToken.IsCancellationRequested)
{
HttpListenerContext ctx = null;
try
{
ctx = await _httpListener.GetContextAsync();
}
catch (HttpListenerException ex)
{
if (ex.ErrorCode == 995) return;
}
if (ctx == null) continue;
var response = ctx.Response;
response.ContentType = "text/plain";
response.Headers.Add(HttpResponseHeader.CacheControl, "no-store, no-cache");
response.StatusCode = (int)HttpStatusCode.OK;
var messageBytes = Encoding.UTF8.GetBytes("Healthy");
response.ContentLength64 = messageBytes.Length;
await response.OutputStream.WriteAsync(messageBytes, 0, messageBytes.Length);
response.OutputStream.Close();
response.Close();
}
}
}
What I've done to accomplish this is add Microsoft.NET.Sdk.Web to my Worker, and then configured a web host to run alongside the worker:
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(builder =>
{
builder.UseStartup<Startup>();
})
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
services.AddLogging(builder =>
builder
.AddDebug()
.AddConsole()
);
});
With that done, all that's left to do is map the health check endpoint as you normally would with ASP.NET Core.

How to handle state and configure cosmos db storage in a nested dialog? (bot framewrok v4)

I am trying to build a chatbot with nested dialogs which is supposed to gather information from the user and store it in Azure CosmosDB. The dialog worked fine until I implemented the Cosmos DB storage. Now, with the CosmosDB storage the dialog loops on the first task in the first dialog, instead of continuing. How can I solve this problem?
Beginning with the dialogs, and how it was before implementing CosmosDB storage. I basically followed the code in this sample 43.complex-dialog.
Then, implementing the storage I used this answer as a guide. I set up the cosmosDB storage in Startup.cs like this:
public class Startup
{
private const string CosmosServiceEndpoint = "MyCosmosServiceEndpoint";
private const string CosmosDBKey = "MyCosmosDBKey";
private const string CosmosDBDatabaseName = "MyCosmosDBDatabaseName";
private const string CosmosDBCollectionName = "MyCosmosDBCollectionName";
private const string CosmosDBPartitionKey = "MyCosmosDBPartitionKey";
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
var storage = new CosmosDbStorage(new CosmosDbStorageOptions
{
AuthKey = CosmosDBKey,
CollectionId = CosmosDBCollectionName,
CosmosDBEndpoint = new Uri(CosmosServiceEndpoint),
DatabaseId = CosmosDBDatabaseName,
PartitionKey = CosmosDBPartitionKey
});
var conversationState = new ConversationState(storage);
var userState = new UserState(storage);
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();
services.AddSingleton<MainDialog>();
services.AddTransient<IBot, WelcomeBot<MainDialog>>();
services.AddSingleton<IStorage, MemoryStorage>();
services.AddSingleton(userState);
services.AddSingleton(conversationState);
services.AddSingleton(userState.CreateProperty<UserProfile>("MyUserState"));
services.AddSingleton(conversationState.CreateProperty<DialogState>("MyBotDialogState"));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseMvc();
}
}
}
My main bot looks like this (don't mind the name "Echobot"):
public class EchoBot<T> : ActivityHandler where T : Dialog
{
private readonly BotState _userState;
private readonly BotState _conversationState;
private readonly Dialog _dialog;
private readonly ILogger _logger;
private readonly IStatePropertyAccessor<UserProfile> _userStateAccessor;
private readonly IStatePropertyAccessor<DialogState> _conversationDialogStateAccessor;
// Create cancellation token (used by Async Write operation).
public CancellationToken CancellationToken { get; private set; }
public EchoBot(ConversationState conversationState, UserState userState, T dialog, ILogger<EchoBot<T>> logger, IStatePropertyAccessor<UserProfile> userStatePropertyAccessor, IStatePropertyAccessor<DialogState> dialogStatePropertyAccessor)
{
_conversationState = conversationState;
_userState = userState;
_dialog = dialog;
_logger = logger;
_userStateAccessor = userStatePropertyAccessor;
_conversationDialogStateAccessor = dialogStatePropertyAccessor;
}
public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default)
{
await base.OnTurnAsync(turnContext, cancellationToken);
var currentUserState = await _userStateAccessor.GetAsync(turnContext, () => new UserProfile(), cancellationToken);
var currentConversationDialogState = await _conversationDialogStateAccessor.GetAsync(turnContext, () => new DialogState(), cancellationToken);
await _userStateAccessor.SetAsync(turnContext, currentUserState, cancellationToken);
await _conversationDialogStateAccessor.SetAsync(turnContext, currentConversationDialogState, cancellationToken);
// Save any state changes that might have occured during the turn.
await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
await _userState.SaveChangesAsync(turnContext, false, cancellationToken);
}
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken=default)
{
_logger.LogInformation("Running dialog with Message Activity.");
//See DialogExtension.cs in the sample "complex-dialog" to see the Run method.
await _dialog.Run(turnContext, _conversationDialogStateAccessor, cancellationToken);
}
}
}
For now, it should work if you remove the PartitionKey parameter from CosmosDbStorageOptions. You will likely need to delete your Container or use a different name, since yours is currently partitioned. Easiest to just delete your Container and let the bot make one for you.
There's currently a bug in all the Bot Builder SDKs around reading from partitioned databases when the partitionKey is supplied. Tracking the issue here

Categories