Microsoft.Rest.ValidationException While trying to create a reply - botframework

I'm using the Microsoft Bot Framework with C# and I'm trying to create a reply message with an image like so:
IMessageActivity m = Activity.CreateMessageActivity();
var images = doc.DocumentNode.SelectNodes("//img[#src]").ToList();
var src = images[10].GetAttributeValue("src", null);
Attachment att = new Attachment();
att.ContentType = "image";
att.ContentUrl = src;
m.Attachments.Add(att);
await context.PostAsync(m);
context.Wait(MessageReceived);
I know that the image source is being extracted correctly but I still get the error:
Microsoft.Rest.ValidationException
What is the cause of this and how do I fix it?
I expect to have a message with the image attached but instead I just get the default bot code error message.
Edit: this is the exception message - 'ReplyToId' cannot be null.

If you are creating a message using the Activity.CreateMessageActivity() then you need to specify the details of user account(ToId,ToName), bot account(FromId, FromName) and conversation(conservationId, channelId).
eg:
var userAccount = new ChannelAccount(toId,toName);
var botAccount = new ChannelAccount(fromId, fromName);
var connector = new ConnectorClient(new Uri(serviceUrl));
IMessageActivity message = Activity.CreateMessageActivity();
if (!string.IsNullOrEmpty(conversationId) && !string.IsNullOrEmpty(channelId))
{
message.ChannelId = channelId;
}
else
{
conversationId = (await connector.Conversations.CreateDirectConversationAsync( botAccount, userAccount)).Id;
}
message.From = botAccount;
message.Recipient = userAccount;
message.Conversation = new ConversationAccount(id: conversationId);
message.Text = "The text you want to send";
//You can add your attachment here
message.Locale = "en-Us";
await connector.Conversations.SendToConversationAsync((Activity)message);
Looking at your code it looks like you can access the context of the Dialog since you are posting the message using context.PostAsync, so the easier way would be to send a message using the context since the context will already contain the details of user, bot and conversation.
You can do this by using context.MakeMessage()
eg:
IMessageActivity reply = context.MakeMessage();
var images = doc.DocumentNode.SelectNodes("//img[#src]").ToList();
var src = images[10].GetAttributeValue("src", null);
Attachment att = new Attachment();
att.ContentType = "image/png";
att.ContentUrl = src;
reply.Attachments.Add(att);
await context.PostAsync(reply);
context.Wait(MessageReceived);

Related

Bad Request when sending Inline Picture as a MS Team Bot

I am receiving bad request when I including an attachment as an inline picture for the MS Teams Bot using the following code (the code works without attachments):
var message = Activity.CreateMessageActivity();
message.Text = "message here";
message.Attachments = new List<Attachment>();
var webClient = new WebClient();
byte[] imageBytes = webClient.DownloadData("https://img.icons8.com/windows/452/showing-small-size.png");
string url = "data:image/png;base64," + Convert.ToBase64String(imageBytes);
message.Attachments.Add(new Attachment
{
ContentType = "image/png",
ContentUrl = url
});
var conversationParameters = new ConversationParameters
{
IsGroup = true,
ChannelData = new TeamsChannelData
{
Channel = new ChannelInfo(outputChannelId),
},
Activity = (Activity)message
};
var response = await connectorClient.Conversations.CreateConversationAsync(conversationParameters);
I received the following error:
Microsoft.Bot.Schema.ErrorResponseException: Operation returned an invalid status code 'BadRequest'
at Microsoft.Bot.Connector.Conversations.CreateConversationWithHttpMessagesAsync
Thanks in advance!
Rather than including the image as an attachment, consider instead sending an Adaptive Card and you can display the image directly to the user. See more on Adaptive Cards here.
As an alternative if you don't want to show the image but it's hosted somewhere, just include a link to it in the text message, using the markdown format that regular text message support in Teams (see more here).

Cortana skill card element action is not firing

I have enabled signin card in my BOT framework to redirect to the client application URL and it worked perfectly find in the BOT emulator and from the WEBCHAT. But i have issues in the Cortana channel.
While clicking on the button, instead of opening a default browser with the client application ur, a popup opens and says 'we cant connect to the service right now. check your network connection or try again'
Here is my code sample in the BOT framework::
public async Task getmypersonalData(IDialogContext context, LuisResult result)
{
string convid = _convid;
ConnectorClient connector = new ConnectorClient(new Uri(_serviceURL));
var replyToConversation = context.MakeMessage();
// Activity replyToConversation = _activity.CreateReply();
replyToConversation.Recipient = new ChannelAccount(id: _fromAddess);// _activity.From;
replyToConversation.Type = "message";
replyToConversation.Attachments = new List<Attachment>();
List<CardAction> cardButtons = new List<CardAction>();
CardAction plButton = new CardAction()
{
Value = $"{System.Configuration.ConfigurationManager.AppSettings["AppWebSite"]}?conversationid={HttpUtility.UrlEncode(convid)}",
Type = "signin",
Title = "Authentication Required"
};
cardButtons.Add(plButton);
SigninCard plCard = new SigninCard("Please login to the application to access this feature", new List<CardAction>() { plButton });
Attachment plAttachment = plCard.ToAttachment();
replyToConversation.Attachments.Add(plAttachment);
await context.PostAsync(replyToConversation);
}

Android post image to Facebook comment

This is a followup to my previous question: Xamarin.Forms App return data to calling App
That works perfectly and I can share images to anywhere, except to Facebook comments. When I click the camera on the content box the app can be selected, I can select the image, Set result and Finish are called, and the app closes and it sends data to Facebook, and then however I then get the error : The image could not be uploaded, try again?
I can't find any fundamental differences between posting to a status or a comment, so I'm guessing it's subtle. Any thoughts on how I can change my intent to post properly?
Adding for completeness:
Bitmap b = null;
string url;
if (!string.IsNullOrEmpty(this.saleItems[i].ImageUrl))
{
url = this.saleItems[i].ImageUrl;
}
else
{
url = await FileHelper.GetLocalFilePathAsync(this.saleItems[i].Id);
}
//download
using (var webClient = new WebClient())
{
var imageBytes = webClient.DownloadData(url);
if (imageBytes != null && imageBytes.Length > 0)
{
b = BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length);
}
}
//set local path
var tempFilename = "test.png";
var sdCardPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
var filePath = System.IO.Path.Combine(sdCardPath, tempFilename);
using (var os = new FileStream(filePath, FileMode.Create))
{
b.Compress(Bitmap.CompressFormat.Png, 100, os);
}
b.Dispose();
var imageUri = Android.Net.Uri.Parse($"file://{sdCardPath}/{tempFilename}");
var sharingIntent = new Intent();
sharingIntent.SetAction(Intent.ActionSend);
sharingIntent.SetType("image/*");
sharingIntent.PutExtra(Intent.ExtraText, "some txt content");
sharingIntent.PutExtra(Intent.ExtraStream, imageUri);
sharingIntent.AddFlags(ActivityFlags.GrantReadUriPermission);
//await SaleItemDataService.Instance.BuySaleItemAsync(this.saleItem);
SetResult(Result.Ok, sharingIntent);
Finish();
Use below:
Intent sharingIntent = new Intent();
string imageUri = "file://" + requestedUri;
sharingIntent.SetData(Android.Net.Uri.Parse(imageUri));

Web url cannot be empty for url type button

var msg = context.MakeMessage();
msg.Attachments = new List<Attachment>();
SigninCard card = new SigninCard()
{
Text= "link it",
Buttons = new List<CardAction>
{
new CardAction
{
Value = "account linking url https",
Type = "account_link",
Title = "Link"
},
}
};
msg.Attachments.Add(card.ToAttachment());
await context.PostAsync(msg);
I'm trying to use SignInCard to link Facebook account.
This error appears:
{"error":{"message":"(#100) Web url cannot be empty for url type
button","type":"OAuthException","code":100,"error_subcode":2018041,"fbtrace_id":"GclYUUuTL2D"}}
But there is a string https url in url field.
Any idea ?
I figured this out.
var msg = context.MakeMessage();
dynamic messageData = new JObject();
messageData.attachment = new JObject();
messageData.attachment.type = "template";
messageData.attachment.payload = new JObject();
messageData.attachment.payload.template_type = "generic";
messageData.attachment.payload.elements
= new JArray(
new JObject(
new JProperty("title", "title"),
new JProperty("subtitle", "Link your account"),
new JProperty("buttons",
new JArray(
new JObject(
new JProperty("type", "account_link"),
new JProperty("url", "yourUrl")
)
)
)
)
);
msg.ChannelData = messageData;
await context.PostAsync(msg);
You don't have to get into channel-specific ChannelData. In your SigninCard's Buttons initializer, instead of
Type = "account_link",
use
Type = ActionTypes.Signin,
Worked on my Facebook Messenger channel.

BotFramework 1:1 conversation throws error "activityid can not be null"

While trying to create a 1:1 conversation using the following code, I get the error saying "activityid cannot be null" can someone please help me pointing out what is wrong?
var newRecipient = new ChannelAccount();
newRecipient.Name = user.Mentioned.Name;
newRecipient.Id = user.Mentioned.Id;
var ConversationId = await connector.Conversations.CreateDirectConversationAsync(activity.Recipient, newRecipient);
IMessageActivity message = Activity.CreateMessageActivity();
message.From = activity.Recipient;
message.Recipient = newRecipient;
message.Conversation = new ConversationAccount(id: ConversationId.Id);
message.Text = $"Congratulations {user.Mentioned.Name}!, you have got a :tangerine: from {activity.From.Name}";
message.Locale = "en-Us";
message.Id = Guid.NewGuid().ToString();
var reply = await connector.Conversations.ReplyToActivityAsync((Activity)message);
You are using:
ReplyToActivityAsync
but not replying to the existing converstation, but rather creating a new one. You should use the following instead:
SendToConversationAsync

Resources