Bot Builder SDK 4 How to work with attachments? - c#

Bot Builder SDK 4 (dotnet) How to work with attachments ? I tried to use the example of BotBuilder-Samples 15.handling-attachments, but got 401 Unauthorized error with Skype channel.
foreach (var file in activity.Attachments)
{
// Determine where the file is hosted.
var remoteFileUrl = file.ContentUrl;
// Save the attachment to the system temp directory.
var localFileName = Path.Combine(Path.GetTempPath(), file.Name)
// Download the actual attachment
using (var webClient = new WebClient())
{
webClient.DownloadFile(remoteFileUrl, localFileName); <-- 401 here
}

I have discovered solution at github.com discussion Skype Can not receive attachment? #3623 which I also have just tested with success.
I see minimal modification to your code sample as follows:
string channelToken = null;
if ((activity.ChannelId.Equals("skype", StringComparison.InvariantCultureIgnoreCase))
{
var credentials = new MicrosoftAppCredentials(youBotAppId, yourBotAppPassword);
channelToken = await credentials.GetTokenAsync();
}
foreach (var file in activity.Attachments)
{
// Determine where the file is hosted.
var remoteFileUrl = file.ContentUrl;
// Save the attachment to the system temp directory.
var localFileName = Path.Combine(Path.GetTempPath(), file.Name)
// Download the actual attachment
using (var webClient = new WebClient())
{
if (!string.IsNullOrWhiteSpace(channelToken))
{
webClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", channelToken);
}
webClient.DownloadFile(remoteFileUrl, localFileName);
}

Related

Why does AWS Lambda not upload images to S3 properly in .NET?

I'm having an issue with .NET 6 framework regarding the uploading of image files to S3 using the AWS SDK.
When I POST to my endpoint running on a local IIES it works perfectly and I can see the generated file in S3 without any issues.
The problem is the following: After a serverless deployment to AWS Lambda, the same .NET Core endpoint that produced a perfect result in my local environment behaves way different when it's running on a lambda. when I try to open the image it shows a square dot at the center but no image.
I am using IFormFile and here is my code
public async Task<string> Upload(IFormFile formfile, string name)
{
var xbuilder = WebApplication.CreateBuilder();
var _AwsSetting = xbuilder.Configuration.GetSection("AwsCredentials").Get<AWSCredentials>();
var accessKey = _AwsSetting.AWSAccessKey;
var secretKey = _AwsSetting.AWSSecretAccessKey;
RegionEndpoint bucketRegion = RegionEndpoint.APSouth1;
var bucketName = _AwsSetting.AWSS3BucketName;
var location = $"{name + Path.GetExtension(formfile.FileName)}";
var contentType = formfile.ContentType;
var client = new AmazonS3Client(accessKey, secretKey, bucketRegion);
try
{
using (var stream = new MemoryStream())
{
await formfile.CopyToAsync(stream);
var putRequest = new PutObjectRequest()
{
Key = location,
BucketName = bucketName,
InputStream = stream,
CannedACL = S3CannedACL.PublicRead,
ContentType=contentType
};
await client.PutObjectAsync(putRequest);
string publicUrl = string.Empty;
publicUrl = $"https://{bucketName}.s3.{bucketRegion.SystemName}.amazonaws.com/{location}";
return publicUrl;
}
}
catch (Exception e)
{
throw e;
}
}

Can not upload image to google cloud bucket using c# windows application

Hello I have created a windows application which uploads image from hdd to google cloud server.
My code was working perfectly but after changing bucket name it is not working.
My both buckets are in the same project and I have given OAuth 2.0 to my project.
even there is no error showing while processing. Please help me.
string bucketForImage = ConfigurationManager.AppSettings["BucketName"];
string projectName = ConfigurationManager.AppSettings["ProjectName"];
string Accountemail = ConfigurationManager.AppSettings["Email"];
var clientSecrets = new ClientSecrets();
clientSecrets.ClientId = ConfigurationManager.AppSettings["ClientId"];
clientSecrets.ClientSecret = ConfigurationManager.AppSettings["ClientSecret"];
string gcpPath = #"D:\mrunal\tst_mrunal.png";
var scopes = new[] { #"https://www.googleapis.com/auth/devstorage.full_control" };
var cts = new CancellationTokenSource();
var userCredential = await GoogleWebAuthorizationBroker.AuthorizeAsync(clientSecrets, scopes, Accountemail, cts.Token);
var service = new Google.Apis.Storage.v1.StorageService();
var bucketToUpload = bucketForImage;
var newObject = new Google.Apis.Storage.v1.Data.Object()
{
Bucket = bucketToUpload,
Name = "mrunal.png"
};
fileStream = new FileStream(gcpPath, FileMode.Open);
var uploadRequest = new Google.Apis.Storage.v1.ObjectsResource.InsertMediaUpload(service, newObject,
bucketToUpload, fileStream, "image/png");
uploadRequest.OauthToken = userCredential.Token.AccessToken;
await uploadRequest.UploadAsync();
//uploadRequest.UploadAsync();
if (fileStream != null)
{
fileStream.Dispose();
}
Did you try this same code for the older bucket and it worked? It seems to me that there is an issue with line of code, uploadRequest.OauthToken = userCredential.Token.AccessToken. You are calling the Token.AccessToken directly from the userCredentials. These methods should be called from the userCredentials.Result.

How can I post image from UWP to .NET core web api?

Now I have configured for UWP photo post to web api part which is using HttpClient.
Uri uri = new Uri("http://localhost:50040/api/Upload");
IInputStream inputStream = await photoFile.OpenAsync(FileAccessMode.Read);
HttpMultipartFormDataContent multipartContent = new HttpMultipartFormDataContent();
multipartContent.Add(new HttpStreamContent(inputStream), "myFile", photoFile.Name);
Windows.Web.Http.HttpClient newclient = new Windows.Web.Http.HttpClient();
Windows.Web.Http.HttpResponseMessage response = await client.PostAsync(uri, multipartContent);
But I don't know how to set for the server side which is my .NET core web api to get the image which post from my UWP application.Please Help me, thank you.
But I don't know how to set for the server side which is my .NET core web api
Please reference the File uploads official tutorial to create your server side. For example, add POST method as following sample code showed to receive the UWP client sent file with the client code you showed above.
// POST api/values
[HttpPost]
public async Task<IActionResult> Post(IFormFile myFile)
{
// full path to file in temp location, you could change this
var filePath = Path.GetTempFileName();
if (myFile.Length > 0)
{
using (var stream = new FileStream(filePath, FileMode.Create))
{
await myFile.CopyToAsync(stream);
}
}
// process uploaded files
// Don't rely on or trust the FileName property without validation.
return Ok(new { filePath, myFile.Length });
}
More details you could also reference the official sample.
In Web API Controller
public IHostingEnvironment _environment;
public UploadFilesController(IHostingEnvironment environment) // Create Constructor
{
_environment = environment;
}
[HttpPost("UploadImages")]
public Task<ActionResult<string>> UploadImages([FromForm]List<IFormFile> allfiles)
{
string filepath = "";
foreach (var file in allfiles)
{
string extension = Path.GetExtension(file.FileName);
var upload = Path.Combine(_environment.ContentRootPath, "ImageFolderName");
if (!Directory.Exists(upload))
{
Directory.CreateDirectory(upload);
}
string FileName = Guid.NewGuid() + extension;
if (file.Length > 0)
{
using (var fileStream = new FileStream(Path.Combine(upload, FileName), FileMode.Create))
{
file.CopyTo(fileStream);
}
}
filepath = Path.Combine("ImageFolderName", FileName);
}
return Task.FromResult<ActionResult<string>>(filepath);
}
In yourpage.xaml.cs
using Windows.Storage;
using Windows.Storage.Pickers;
.....
StorageFile file;
......
private async void btnFileUpload_Click(object sender, RoutedEventArgs e) // Like Browse button
{
try
{
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".png");
file = await openPicker.PickSingleFileAsync();
if (file != null)
{
//fetch file details
}
}
catch (Exception ex)
{
}
}
//When upload file
var http = new HttpClient();
var formContent = new HttpMultipartFormDataContent();
var fileContent = new HttpStreamContent(await file.OpenReadAsync());
formContent.Add(fileContent, "allfiles", file.Name);
var response = await http.PostAsync(new Uri("Give API Path" + "UploadImages", formContent);
string filepath = Convert.ToString(response.Content); //Give path in which file is uploaded
Hope this code helps you...
But remember formContent.Add(fileContent, "allfiles", file.Name); line is important and allfiles is that name of parameter to fetch files in web api method "public Task<ActionResult<string>> UploadImages([FromForm]List<IFormFile> **allfiles**)"
Thanks!!!

How to stream zip file from TFS api

I am using TFS2018 api and I am trying to to retrieve the zip file of a solution but I always get an internal server error.
internal async Task<bool> GetSourceZipFile(string sourceVersionId)
{
using (var handler = new HttpClientHandler { Credentials = new NetworkCredential(tfsUser, tfsPass) })
using (var client = new HttpClient(handler))
{
try
{
client.BaseAddress = new Uri(tfsServer);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/octet-stream"));
var tempFolder = "c:\\temp\\test";
tempFolder = HttpUtility.UrlEncode(tempFolder);
var url = $"DefaultCollection/_api/_versioncontrol/itemContentZipped?path={tempFolder}&version={sourceVersionId}";
using (var file = await client.GetStreamAsync(url).ConfigureAwait(false))
using (var memoryStream = new MemoryStream())
{
await file.CopyToAsync(memoryStream);
var s = memoryStream.ToArray();
var f = s;
};
}
catch (Exception ex)
{
// LOGGING
}
return true;
}
}
I am not sure if the zip file is generated by the TFS server. Do I need to set it specifically? Any idea why this is not working?
You're passing in a local folder to the path parameter in the REST API. The path should be to the item in source control (ex: $/MyTeamProject/DEV/SomeCode), not to the local file system.

Office 365 Sharepoint Upload Files to Documents Library

I am trying to use the following code to add files to my document library on Sharepoint Office365 using web services.
public void SaveFileToSharePoint(string fileName)
{
try
{
var copyService = new Copy { Url = "https://mydomain.com/_vti_bin/copy.asmx", Credentials = new NetworkCredential("username", "password", "domain") };
var destURL = "https://mydomain.com/Shared%20Documents/" + Path.GetFileName(fileName);
string[] destinationUrl = { destURL };
CopyResult[] cResultArray;
var fFiledInfo = new FieldInformation { DisplayName = "Description", Type = FieldType.Text, Value = Path.GetFileName(fileName) };
FieldInformation[] fFiledInfoArray = {fFiledInfo};
var copyresult = copyService.CopyIntoItems(destURL, destinationUrl, fFiledInfoArray, File.ReadAllBytes(fileName), out cResultArray);
var b = copyresult;
}
catch (Exception ex)
{
}
}
I receive the error "Object Moved". The URL loads the WSDL in the browser though. If there is a better way to upload and get files from SharePoint on Office365 online I would entertain that as well. Thanks.
as the ASMX webservices are deprecated you should check out the "new" rest services of sharepoint. ON MSDN you find information about it
Or you can use the Client object model which would be my favorite way. The following example shows basic usage, to connect to SharePoint online check out the following link
using(ClientContext context = new ClientContext("http://yourURL"))
{
Web web = context.Web;
FileCreationInformation newFile = new FileCreationInformation();
newFile.Content = System.IO.File.ReadAllBytes(#"C:\myfile.txt");
newFile.Url = "file uploaded via client OM.txt";
List docs = web.Lists.GetByTitle("Documents");
Microsoft.SharePoint.Client.File uploadFile = docs.RootFolder.Files.Add(newFile);
context.ExecuteQuery();
}
Using roqz suggestions above, here is the ultimate solution I came up with to place files in the SharePoint 2013 Office 365 document library and to retrieve them by name:
public void SaveFileToSharePoint(string fileName)
{
using (var context = new ClientContext("https://mydomain.com/"))
{
var passWord = new SecureString();
foreach (var c in "MyPassword") passWord.AppendChar(c);
context.Credentials = new SharePointOnlineCredentials("me#mydomain.com", passWord);
var web = context.Web;
var newFile = new FileCreationInformation {Content = File.ReadAllBytes(fileName), Url = Path.GetFileName(fileName)};
var docs = web.Lists.GetByTitle("Documents");
docs.RootFolder.Folders.GetByUrl("Test").Files.Add(newFile);
context.ExecuteQuery();
}
}
public void GetFileFromSharePoint(string fileName, string savePath)
{
using (var context = new ClientContext("https://mydomain.com/"))
{
var passWord = new SecureString();
foreach (var c in "MyPassword") passWord.AppendChar(c);
context.Credentials = new SharePointOnlineCredentials("me#mydomain.com", passWord);
var web = context.Web;
var myFile = web.Lists.GetByTitle("Documents").RootFolder.Folders.GetByUrl("Test").Files.GetByUrl(fileName);
context.Load(myFile);
context.ExecuteQuery();
using (var ffl = Microsoft.SharePoint.Client.File.OpenBinaryDirect(context, myFile.ServerRelativeUrl))
{
using (var destFile = File.OpenWrite(savePath + fileName))
{
var buffer = new byte[8*1024];
int len;
while ((len = ffl.Stream.Read(buffer, 0, buffer.Length)) > 0)
{
destFile.Write(buffer, 0, len);
}
}
}
}
}

Categories

Resources