Upload a text file as attachment using Bot framework not working in Skype channel - botframework

I am unable to upload a text file as an attachment using the Bot framework (Bot.Builder v3.11.0), when trying in the Skype channel. It worked in the Bot framework emulator though. Following is the code which uploads a file and to returns the activity with the uploaded file URL in the attachment. It throws an exception when using the Skype channel. Alternatively is there any other way to achieve uploading/attaching a text file in the Skype channel which the user can then download from within the client?
public static async Task<Activity> GetTextAttachmentAsync(Activity message)
{
var reply = message.CreateReply("Here is a text attachment");
var serviceUrl = reply.ServiceUrl;
var conversationId = reply.Conversation.Id;
byte[] fileData = null;
using (var wc = new System.Net.WebClient())
fileData = wc.DownloadData("https://textfiles.com/100/adventur.txt");
using (var connector = new ConnectorClient(new Uri(serviceUrl)))
{
var attachments = new Attachments(connector);
var token = await (connector.Credentials as MicrosoftAppCredentials).GetTokenAsync();
connector.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var response = await attachments.Client.Conversations.UploadAttachmentAsync(
conversationId,
new AttachmentData
{
Name = "transcript.html",
OriginalBase64 = fileData,
Type = "text/html"
});
reply.Attachments = new List<Attachment>
{
new Attachment
{
Name = "transcript.html",
ContentType = "text/html",
ContentUrl = attachments.GetAttachmentUri(response.Id)
}
};
return reply;
}
}
Exception thrown from the UploadAttachmentAsync() function above:
Microsoft.Rest.HttpOperationException: Not Found
at Microsoft.Bot.Connector.ErrorHandling.<HandleErrorAsync>d__2`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Bot.Connector.ConversationsExtensions.<UploadAttachmentAsync>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Support.Services.Bot.Core.Utilities.AdaptiveCardsHelper.<GetTextAttachmentAsync>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Support.Services.Bot.Core.Dialogs.BotDialog.<HandleMessageAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Support.Services.Bot.Core.Dialogs.DialogBase`1.<MessageReceivedAsync>d__8.MoveNext()

When running your code with Common Language Runtime Errors enabled in Visual Studio. I got the following error:
It seems that the site address https://textfiles.com/100/adventur.txt does not have a trusted certificate and that makes .NET unhappy. When I went to investigate, I found this Stack Overflow answer that suggested using this code below to overcome this but is strongly recommended not to use this in production.
ServicePointManager.ServerCertificateValidationCallback += (o, c, ch, er) => true;
This was going to be my original suggestion before I ran your code: many channels (Skype included), limit the types of files you are able to send from a bot when using base64 and/or local files. For example, I know that you cannot send PDF files as Base64 in Skype. If memory serves correctly, you can only send image and video files (maybe audio too) using the base64 method in Skype. So even if you resolve this error you may run into this afterward. The workaround for this is using hosted files. I'm not exactly sure what you are trying to do with your bot, so I'm not sure if this is an option for you specifically, but it is an option.
So if you find this code not working after resolving the certificate issue, try sending an image file and see if that works, if it does but your HTML file still fails, you will know this is why.

Related

Catastrophic failure(Exception HRESULT: 0x8000FFFF (E_UNEXPECTED)) while trying to use MS WebView2 in ASP,NET Web API in production environment

I'm getting 'Catastrophic failure(Exception HRESULT: 0x8000FFFF (E_UNEXPECTED))' run-time error while trying to use MS WebView2 in ASP.NET Web API in production environment (Win10, IIS v.20H2 (OS Build 19042, 1586)) - see details in the code inline.
When the same code is used in a .NET Framework console app or under VS2019/Kestrel(?) (Ctrl+F5 - Start without debugging) everything works well.
private ManualResetEvent _event;
public void StartBrowserThread()
{
var th = new Thread(async () =>
{
BrowserFormsLogger.Log($"th.Context = {contextDescription}");
var webView = new Microsoft.Web.WebView2.WinForms.WebView2();
...
udf = ...
var envTask = await Microsoft.Web.WebView2.Core.CoreWebView2Environment
.CreateAsync(userDataFolder: udf);
var ecwTask = webView.EnsureCoreWebView2Async(envTask);
while (ecwTask.IsCompleted == false)
{
Application.DoEvents();
//
// Run-time error happens here in ASP.NET environment after .DoEvents called several thousand times.
// In a .NET Framework Console App everything works well.
//
// WebView2 creation failed with exception = System.Runtime.InteropServices.COMException (0x8000FFFF):
// Catastrophic failure(Exception HRESULT: 0x8000FFFF (E_UNEXPECTED))
// in System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
// in Microsoft.Web.WebView2.Core.CoreWebView2Environment.<CreateCoreWebView2ControllerAsync>d__58.MoveNext()
// --- End of stack trace from previous location where exception occurred ---
// in System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
// in System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
// in System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
// in Microsoft.Web.WebView2.WinForms.WebView2.<InitCoreWebView2Async>d__18.MoveNext()
};
...
_event.Set();
System.Windows.Forms.Application.Run();
});
th.SetApartmentState(ApartmentState.STA);
th.IsBackground = true;
_event = new ManualResetEvent(false);
th.Start();
...
Any clues how this issue can be solved?

Set Teams Picture using graph API

I am trying to set the team's picture using graph API. I am using the SDK version.
byte[] imageArray = System.IO.File.ReadAllBytes(#"D:\TeamPhoto.png");
string base64ImageRepresentation = Convert.ToBase64String(imageArray);
byte[] bytes = Convert.FromBase64String(base64ImageRepresentation);
using (MemoryStream ms = new MemoryStream(bytes))
{
var d = await graphClient.Groups[teamId].Photo.Content
.Request()
.PutAsync(ms);
}
But I am getting an error
Unable to to set photo of target in Outlook Exchange Photo API:
PhotoApiCallServiceException
Can anyone please tell me what am I missing here?
StackTrace:
at Microsoft.Graph.HttpProvider.<SendAsync>d__18.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Graph.BaseRequest.<SendRequestAsync>d__40.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Graph.BaseRequest.<SendStreamRequestAsync>d__36.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
Thanks in advance.

I cannot access ApplicationData.Current from Win32 unpackaged app?

My code:
using System;
using Windows;
namespace SampleSynthesis {
class Program {
static async System.Threading.Tasks.Task Main(string[] args) {
var synth = new Windows.Media.SpeechSynthesis.SpeechSynthesizer();
Windows.Media.SpeechSynthesis.SpeechSynthesisStream stream =
await synth.SynthesizeTextToStreamAsync("I want to listen to this text");
using (var reader = new Windows.Storage.Streams.DataReader(stream)) {
await reader.LoadAsync((uint)stream.Size);
Windows.Storage.Streams.IBuffer buffer = reader.ReadBuffer((uint)stream.Size);
Windows.Storage.StorageFile file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync("audio.wav");
await Windows.Storage.FileIO.WriteBufferAsync(file, buffer);
}
}
}
Compiled with this command:
"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\Roslyn\csc.exe" /r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.Speech.dll","C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5\System.Runtime.WindowsRuntime.dll","C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.runtime.dll","C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.17763.0\Windows.winmd","C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.Threading.Tasks.dll" tts.cs
I am getting:
Unhandled Exception: System.InvalidOperationException: The process has no package identity. (Exception from HRESULT: 0x80073D54)
at Windows.Storage.ApplicationData.get_Current()
at SampleSynthesis.Program.<Main>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at SampleSynthesis.Program.<Main>(String[] args)
Maybe exists another way to save wav? I know that I can use simpler SetOutputToWaveFile() but because of cracks in the synthesized audio I want to try some another method. I need to use Desktop Bridge? Instead of Windows.Storage.ApplicationData.Current.LocalFolder I tried Windows.Storage.ApplicationData.Current.TemporaryFolder and got the same exception.
Windows.Storage.ApplicationData.Current only applies to packaged apps that have an identity (UWP apps and Desktop Bridge apps). Unpackaged Win32 EXE don't have the concept of their own isolated app data.
It's not clear why you need to this here, or what you are trying to accomplish. This shouldn't have anything to do with cracks in the audio playback.

Exception -"Cannot send a content-body with this verb-type" using httpclient.sendasync

Already tried searching SO for similar issues but those didn't help to resolve.
Scenario:
Have a Web Client app which has a Web API app as a backend. There is no issue when calling the same URI if it's from this Client - Web API but the exception happens when I'm trying to trigger the API request from another WebAPI Services application ( say its a separate project for accessing reports which run as a service using Telerik Reporting).
Code:
private async Task<HttpStatusCode> AccessService()
{
HttpResponseMessage response = null;
try
{
using (HttpRequestMessage request = new HttpRequestMessage()
{
Content = new System.Net.Http.StringContent(JSONValues, System.Text.Encoding.UTF8, "application/json"),
RequestUri = new Uri(UriString),
Method = CallMethod
})
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", Utils.Token) ;
response = await httpClient.SendAsync(request);
if (response.IsSuccessStatusCode)
{
string httpResponse = await response.Content.ReadAsStringAsync();
httpString = JsonConvert.DeserializeObject<string[]>(httpResponse);
}
ErrorCode = response.StatusCode;
response.Dispose();
}
}
catch (Exception ex)
{
Misc.Error= ex.Message;
}
finally
{
response.Dispose();
}
return ErrorCode;
}
Exception:
Cannot send a content-body with this verb-type.
at System.Net.HttpWebRequest.CheckProtocol(Boolean onRequestStream)
at System.Net.HttpWebRequest.BeginGetRequestStream(AsyncCallback callback, Object state)
at System.Net.Http.HttpClientHandler.StartGettingRequestStream(RequestState state)
at System.Net.Http.HttpClientHandler.PrepareAndStartContentUpload(RequestState state)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.Http.HttpClient.<FinishSendAsyncBuffered>d__58.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
This works fine when I access the same from the Client app ( asp.net mvc ) and issue happens when I call this from the Report Services API app. Is this has something to with it.
Edit:
The Web client Project is asp.net mvc core 2.1, so I think it works while using content in GET method of HttpClient.SendAsync but the Reports Services App where this issue happens are targets .net 461 .
I strongly doubt this might be the cause since .net framework doesn't allow content for GET operations? Any work arounds?
Link
TIA
Based on the description provided, if you use get method you usually don't have a body in the get request. For more details, please refer to the solutions below:
http://stackoverflow.com/questions/3981564/cannot-send-a-content-body-with-this-verb-type

Using complex route Razor Page routing conventions that involve multiple variables in paths

Background
.NetCore 2 web application targetting the full .Net framework. We are moving from the conventional MVC separate Controller/View structure where we configured route rules using [Route()]/Get() attributes to handle routing to Razor Pages.
So far
Following the MS docs (https://learn.microsoft.com/en-us/aspnet/core/mvc/razor-pages/razor-pages-convention-features#page-model-action-conventions) I have the first tier of folders with a category ID being passed to the page;
e.g. '/category/15032/dashboard/' resolves to the page 'pages/category/dashboard'
`options.Conventions
.AddFolderRouteModelConvention("/category", model =>
{
int selectorCount = model.Selectors.Count;
for (int i = 0; i < selectorCount; i++)
{
SelectorModel selector = model.Selectors[i];
string[] segments = selector.AttributeRouteModel.Template.Split('/');
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 1,
Template = AttributeRouteModel.CombineTemplates($"category/{{categoryid}}/{segments[1].ToLower()}", "{categoryPageTemplate?}")
}
});
}
});`
This works as expected. However, the problems arise when I try to add further depth to the folder structure.
The problem
Each category contains a sub-category, and then within that, an item. For example, I will include a deeply nested page.
e.g. '/category/15032/subcategory/543/item/211/status' should resolve to the page 'pages/category/subcategory/item/status'
The hope was that adding the following convention would handle this;
`options.Conventions
.AddFolderRouteModelConvention("/category/subcategory/item", model =>
{
int selectorCount = model.Selectors.Count;
for (int i = 0; i < selectorCount; i++)
{
SelectorModel selector = model.Selectors[i];
string[] segments = selector.AttributeRouteModel.Template.Split('/');
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 1,
Template = AttributeRouteModel.CombineTemplates($"category/{{categoryid}}/subcategory/{{subcategoryid}}/item/{{itemid}}/{segments[2].ToLower()}",
"{itemPageTemplate?}")
}
});
}
});`
Error
Microsoft.AspNetCore.Routing.RouteCreationException: The following
errors occurred with attribute routing information:
For action: 'Page: /category/subcategory/item/dashboard' Error: The
route parameter name 'categoryid' appears more than one time in the
route template. Parameter name: routeTemplate
at
Microsoft.AspNetCore.Mvc.Internal.AttributeRoute.GetRouteInfos(IReadOnlyList
1 actions) at
Microsoft.AspNetCore.Mvc.Internal.AttributeRoute.AddEntries(TreeRouteBuilder
builder, ActionDescriptorCollection actions) at
Microsoft.AspNetCore.Mvc.Internal.AttributeRoute.GetTreeRouter() at
Microsoft.AspNetCore.Mvc.Internal.AttributeRoute.RouteAsync(RouteContext
context) at
Microsoft.AspNetCore.Routing.RouteCollection.d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.d__7.MoveNext()
Question
Note: the folders are nested like this because there are quite a few pages to the site, so keeping things organised is quite important.
How can I avoid this error? Do I have to change the URL structure - this has proven fairly readable (don't normally use ID numbers)? Does anyone have any examples of a similar nested structure (I have had difficulty in finding examples)?

Resources