问题
I'm trying to kind of merge the functionality of EchoBot
and ProactiveBot
. A bot that parses user commands, which can also be triggered through a URL to send some users a message based on the contents of their UserProfile
.
I managed to get both parts to work, but I'm having trouble accessing the UserProfile
s from the NotifyController
, or solving the problem another way. I tried a few things, read many of the tutorials and also this excellent explanation, but I'm still stuck.
So my question is: How do I rewrite NotifyController
so it calls a method in my Bot class (the one implementing ActivityHandler
) - just like BotController
(from EchoBot
) does?
Or, if that's better: How do I get a reference to the UserProfile
in the message handler in NotifyController
?
Thanks!
回答1:
Alright, I got it to work.
Basically I duplicated all the code for the conversationReferences, because those get stored in the Bot and are used in NotifyController.
Some code, in case somebody else is trying to do the same:
Startup.cs
Create another Singleton.
services.AddSingleton<ConcurrentDictionary<string, UserProfile>>();
In the bot class
I have a variable storing UserProfile
s just like the one for ConversationReference
s
private readonly ConcurrentDictionary<string, ConversationReference> _conversationReferences;
private readonly ConcurrentDictionary<string, UserProfile> _userProfiles;
The constructor now starts like this
public RmindrBot(ConversationState conversationState,
UserState userState,
ConcurrentDictionary<string, ConversationReference> conversationReferences,
ConcurrentDictionary<string, UserProfile> userProfiles)
{
_conversationReferences = conversationReferences;
_userProfiles = userProfiles;
...
(I think this is the most surprising bit for me - didn't think the framework would just magically figure out the new signature.)
A method for adding references:
private void AddConversationReference(Activity activity)
{
var conversationReference = activity.GetConversationReference();
_conversationReferences.AddOrUpdate(
conversationReference.User.Id,
conversationReference,
(key, newValue) => conversationReference);
}
...which is called in OnMessageActivityAsync
:
var userProfile = await userStateAccessors.GetAsync(turnContext, () => new UserProfile());
userProfile.ID = turnContext.Activity.From.Id;
AddUserProfile(userProfile);
NotifyController
private readonly ConcurrentDictionary<string, UserProfile> _userProfiles;
public NotifyController(
IBotFrameworkHttpAdapter adapter,
IConfiguration configuration,
ConcurrentDictionary<string, ConversationReference> conversationReferences)
ConcurrentDictionary<string, ConversationReference> conversationReferences,
ConcurrentDictionary<string, UserProfile> userProfiles)
{
_adapter = adapter;
_conversationReferences = conversationReferences;
_userProfiles = userProfiles;
...
And then we can finally use it in the callback method and match the user to their ID:
private async Task BotCallback(ITurnContext turnContext, CancellationToken cancellationToken)
{
var userProfile = _userProfiles[turnContext.Activity.From.Id];
await turnContext.SendActivityAsync("proactive hello " + userProfile.ID);
}
来源:https://stackoverflow.com/questions/64490008/access-userprofile-from-notifybot