Bad Request when sending Inline Picture as a MS Team Bot - botframework

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).

Related

Microsoft.Rest.ValidationException While trying to create a reply

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);

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);
}

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

How can I attach file to message with Microsoft Bot Framework?

I have Web API service:
[ActionName("download")]
[HttpGet]
public HttpResponseMessage Download()
{
var stream = new FileStream(HostingEnvironment.MapPath("~/tmp/") + "doc.pdf", FileMode.Open);
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StreamContent(stream)
};
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
{
FileName = document.Name + "." + document.AssociatedApplication.Extension
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return result;
}
Bot's code:
if (message.Text.StartsWith("/d"))
{
var contentType = "application/pdf";
var attachment = new Attachment(contentType, "https://localhost/api/documents.download");
var response = await client.GetAsync("https://localhost/api/documents.download");
var data = await response.Content.ReadAsByteArrayAsync();
System.IO.File.WriteAllBytes(HostingEnvironment.MapPath("~/tmp/") + document.Name + "." + document.Extension, data);
var stream = System.IO.File.ReadAllBytes(HostingEnvironment.MapPath("~/tmp/") + document.Name + "." + document.Extension);
attachment.Content = stream;
var msg = message.CreateReplyMessage("This is your document: ");
msg.Attachments = new[] { attachment };
await context.PostAsync(msg);
}
If I change content type on the server and client to "image/png" and send PNG image from server to client then this sample works perfect - in the Bot Framework Emulator I got text "This is your document: " and received image.
But if I try to send PDF document with content type "application/pdf" or "application/octet-stream" and get it on the client with content type "application/pdf" then on the Bot Framework Emulator I got message like that:
This is your document: (https://localhost/api/documents.download)
Is this possible to get in the conversation "real" document instead of link for download (how it works with images)?
PS: This question works only for "image/png" or similar content types.
2 things:
1. it doesn't look like you are setting the content type for the attachment (the code above is using "")
2. Content is not for pushing media files. Our messages are limited to 256k serialized json. If you want to send a document or image you send an attachment with url pointing to the file and contenttype for the file
3. Not all channels have semantics for files other than images and they represent them as links. We use the contenttype to determine if we can do something channel specific for a given attachment.

Allow images in AtomPub ASPNET Web Api Server

I'm trying to create an Atompub service with ASP.NET WEB API, all it's ok but when I try to post any image from Windows Live Writer I get an error "The blog doesn't allow the image load" I'm reading the ietf doc.
My services controller code:
public class ServicesController : ApiController
{
public HttpResponseMessage Get()
{
var serviceDocument = new ServiceDocument();
var workSpace = new Workspace
{
Title = new TextSyndicationContent("Nicoloco Site"),
BaseUri = new Uri(Request.RequestUri.GetLeftPart(UriPartial.Authority))
};
var posts = new ResourceCollectionInfo("Nicoloco Blog",
new Uri(Url.Link("DefaultApi", new { controller = "blogapi" })));
posts.Accepts.Add("application/atom+xml;type=entry");
var images = new ResourceCollectionInfo("Images Blog",
new Uri(Url.Link("DefaultApi", new { controller = "images" })));
images.Accepts.Add("image/png");
images.Accepts.Add("image/jpeg");
images.Accepts.Add("image/jpg");
images.Accepts.Add("image/gif");
var categoriesUri = new Uri(Url.Link("DefaultApi", new { controller = "tags", format = "atomcat" }));
var categories = new ReferencedCategoriesDocument(categoriesUri);
posts.Categories.Add(categories);
workSpace.Collections.Add(posts);
workSpace.Collections.Add(images);
serviceDocument.Workspaces.Add(workSpace);
var response = new HttpResponseMessage(HttpStatusCode.OK);
var formatter = new AtomPub10ServiceDocumentFormatter(serviceDocument);
var stream = new MemoryStream();
using (var writer = XmlWriter.Create(stream))
{
formatter.WriteTo(writer);
}
stream.Position = 0;
var content = new StreamContent(stream);
response.Content = content;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/atomsvc+xml");
return response;
}
}
The http GET Request generate the follow XML:
<?xml version="1.0" encoding="utf-8"?>
<app:service
xmlns:a10="http://www.w3.org/2005/Atom"
xmlns:app="http://www.w3.org/2007/app">
<app:workspace xml:base="http://localhost:53644/">
<a10:title type="text">Nicoloco Site</a10:title>
<app:collection href="http://localhost:53644/api/blogapi">
<a10:title type="text">Nicoloco Blog</a10:title>
<app:accept>application/atom+xml;type=entry</app:accept>
<app:categories href="http://localhost:53644/api/tags?format=atomcat" />
</app:collection>
<app:collection href="http://localhost:53644/api/images">
<a10:title type="text">Images Blog</a10:title>
<app:accept>image/png</app:accept>
<app:accept>image/jpeg</app:accept>
<app:accept>image/jpg</app:accept>
<app:accept>image/gif</app:accept>
</app:collection>
</app:workspace>
</app:service>
But I can't publish images using this service.
Best regards.
I found my error on "categories line", WLW log file shows a malformed XML error in this line, I removed it and all works fine for me... in this blog post explains how WLW Works with image files
If somebody have any comment... I'll be grateful

Resources