I'm struggling with fetching meta data from BlobItem when fetching Blobs from Azure storage.
I'm definitely missing something but can't to figure it out what or where
Here is simple block of code where I'm fetching BlobItems from test container.
Everything is fine on var properties as I did successfully fetch Metadata, but problem lies when I'm trying to fetch data for blob item inside while loop, it returns null
var containerClient = _blobServiceClient.GetBlobContainerClient(AzureStorageHelpers.BlobContainers.Files);
var properties = await containerClient.GetPropertiesAsync();
var blobs = containerClient.GetBlobsAsync();
var enumerator = blobs.GetAsyncEnumerator();
var blobList = new List<BlobItem>();
try
{
while (await enumerator.MoveNextAsync())
{
var blobItem = enumerator.Current;
var metaData = enumerator.Current.Metadata;
var dwaw = blobItem.Metadata["Name"];
blobList.Add(blobItem);
}
}
finally
{
await enumerator.DisposeAsync();
}
I'm getting null value and on Azure I can clearly see that I have defined some test metadata properties.
I'm using NET.Core 2.2 with Nuget Azure.Storage.Blobs(12.5.1)
Try passing the parameter while fetching Blobs:
var blobs = containerClient.GetBlobsAsync(BlobTraits.Metadata);
Refer this link
Related
With Microsoft.WindowsAzure.Storage.Blob one could enumerate a large BLOB container using the BlobContinuationToken in the ListBlobsSegmentedAsync method, and the BlobResultSegment would include the ContinuationToken property if a subsequent read would be required to retrieve more from the container.
With Azure.Storage.Blobs it appears the enumeration API is BlobContainerClient.GetBlobsAsync but the method signature does not provide a means of supplying a continuation token, and the results as Azure.AsyncPageable<BlobItem> do not appear to provide a property that is a continuation token.
Does anyone have a code snippet for enumerating large BLOB containers on Azure, using continuation tokens, via the Azure.Storage.Blobs package?
If you really want to use a continuation token you can do so:
string continuationToken = null;
var container = new BlobContainerClient("xxx", "test");
var blobPages = container.GetBlobsAsync().AsPages();
await foreach (var page in blobPages)
{
continuationToken = page.ContinuationToken;
foreach(var blob in page.Values)
{
...
}
}
You can pass the token to AsPages to continue iteration:
blobPages = container.GetBlobsAsync().AsPages(continuationToken: continuationToken);
or you can just iterate over the blobs, let the SDK do the job of providing all the data using a stream of blobs:
var container = new BlobContainerClient("xxx", "test");
var blobs = container.GetBlobsAsync();
await foreach (var blob in blobs)
{
//
}
Iterating over the blobs can make multiple calls to the blob service.
For more about pagination in the SDK see the docs.
I am trying to extract a list of items in a SharePoint Site below the root site at host.sharepoint.com/sites/mysite. I've tried a bunch of different methods, but only one seems to work:
var host = "host.sharepoint.com:/";
var siteName = "mysite";
var listName = "MyList";
// Generate the Client Connection
var graphHelper = new ApplicationAuthenticatedClient(ClientId, Tenant, ClientSecret);
await graphHelper.ConnectAsync().ConfigureAwait(false);
// Code: itemNotFound
//Message: The provided path does not exist, or does not represent a site
//var list = await graphHelper.GraphClient.Sites[$"{host}{siteName}"].Request().GetAsync();
// Returns a Site, no Lists.
//var list = await graphHelper.GraphClient.Sites[host].Sites[siteName].Request().GetAsync();
//Code: itemNotFound
//Message: The provided path does not exist, or does not represent a site
//var list = await graphHelper.GraphClient.Sites[host].Sites[siteName].Lists[listName].Request().GetAsync();
// List retrieved, but no Items
//var site = await graphHelper.GraphClient.Sites[host].Sites[siteName].Request().Expand("lists").GetAsync();
//var list = await graphHelper.GraphClient.Sites[site.Id].Lists[listName].Request().Expand("Items").GetAsync();
//Code: invalidRequest
//Message: Can only provide expand and select for expand options
//var queryOptions = new List<QueryOption>() { new QueryOption("expand", "fields") };
// This works
var site = await graphHelper.GraphClient.Sites[host].Sites[siteName].Request().GetAsync();
var list = await graphHelper.GraphClient.Sites[site.Id].Lists[listName].Items.Request().Expand("Fields").GetAsync();
I've finally managed to get it to connect, but I'm wondering if there's a better way to navigate to the list, rather than the two API calls? (Assuming that I don't know the Site ID beforehand)
Edit: Using the Graph Explorer, I can access the items using https://graph.microsoft.com/v1.0/sites/{host}.sharepoint.com:/sites/{siteName}:/lists/{listName}/items?expand=fields, but I don't know how to (or if) access that API call in a single call in the .NET API.
It appears that I was on the right track with var list = await graphHelper.GraphClient.Sites[$"{host}{siteName}"].Request().GetAsync(); but the URI was not formatted correctly.
The correct Site ID for https://host.sharepoint.com/sites/mysite/MyList is:
Sites[host.sharepoint.com:/sites/mysite:"]
Retrieving the list from the code in my original question would look like this:
var host = "host.sharepoint.com";
var siteName = "mysite";
var listName = "MyList";
// Generate the Client Connection
var graphHelper = new ApplicationAuthenticatedClient(ClientId, Tenant, ClientSecret);
await graphHelper.ConnectAsync().ConfigureAwait(false);
var list = await graphHelper.GraphClient.Sites[$"{host}:/sites/{siteName}:"].Lists[listName].Request().GetAsync();
it's possible in one API call.
GET https://graph.microsoft.com/v1.0/sites/{host}.sharepoint.com:/sites/{siteName}:/lists/{listTitle}/items?$expand=Fields
Someone has shared a Box.com folder with me using the link. I need to be able to use the C# SDK or REST API to download the documents from their folder.
I have tried all 3 authentication types and have attempted to access with both the C# SDK and REST API.
//SDK attempt
var findFolder = await client.SharedItemsManager.SharedItemsAsync("https://<userWhoSharedWithMe>.box.com/s/<folderHash>"); // notFound
var folder = await client.FoldersManager.GetInformationAsync(findFolder.Id);
var items = folder.ItemCollection;
//API Attempt
var client = new HttpClient
{
BaseAddress = new Uri("https://api.box.com")
};
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "<bearerToken>");
var response = await client.GetAsync("2.0/folders/<folderId>/items");
var content = await response.Content.ReadAsStringAsync();
Is there any way to programmatically download documents from a box folder that was shared with me via link?
-- Edited 06/04/2019
The folder owner and I have tried various things and it seems the API still will not allow me to see the content of the shared folder. Is there anything the folder owner needs to do to make it visible?
Based on the suggestion that I received from a Box employee, I made the following changes.
First the snippet that didn't work as expected:
// DOES NOT WORK
var reader = new StreamReader("box-config.json");
var json = reader.ReadToEnd();
var config = BoxConfig.CreateFromJsonString(json);
var sdk = new BoxJWTAuth(config);
var token = sdk.AdminToken();
var session = new OAuthSession(token, "N/A", 3600, "bearer");
boxClient = new BoxClient(config, session, asUser: boxUserId);
Secondly, the modified version that worked, allowing me to see the folder that was shared to me and allowed me to traverse its contents:
// THIS WORKS !!!!!!!!
var reader = new StreamReader("box-config.json");
var json = reader.ReadToEnd();
var config = BoxConfig.CreateFromJsonString(json);
var sdk = new BoxJWTAuth(config);
var token = sdk.UserToken(boxUserId);
boxClient = sdk.UserClient(token, boxUserId);
And for completeness' sake, here's a snippet of code that will allow you to programmatically access a Box folder and traverse its contents:
//folderId <-- You can find this ID by logging into your box account and navigating to the folder that you're interested in accessing programmatically.
var items = await boxClient.FoldersManager.GetFolderItemsAsync(folderId, limit: 5000, offset: 0, autoPaginate: false,
sort: "name", direction: BoxSortDirection.DESC);
// How many things are this folder?
Console.WriteLine($"TotalCount: {items.TotalCount}");
// Loop through those items
foreach (var item in items.Entries)
{
// Get info on each item
var file = await boxClient.FilesManager.GetInformationAsync(item.Id);
// Print the filename
Console.WriteLine($"file: {item.Name}");
}
I want to upload a file to Azure blob storage asynchronously. I have tried the way suggested in the official sdk:
This is how I get the container:
public static class BlobHelper
{
public static CloudBlobContainer GetBlobContainer()
{
// Pull these from config
var blobStorageConnectionString = ConfigurationManager.AppSettings["BlobStorageConnectionString"];
var blobStorageContainerName = ConfigurationManager.AppSettings["BlobStorageContainerName"];
// Create blob client and return reference to the container
var blobStorageAccount = CloudStorageAccount.Parse(blobStorageConnectionString);
var blobClient = blobStorageAccount.CreateCloudBlobClient();
var container = blobClient.GetContainerReference(blobStorageContainerName);
container.CreateIfNotExists();
container.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob });
return container;
}
}
And this is how i try to upload the file:
var documentName = Guid.NewGuid().ToString();
CloudBlobContainer container = BlobHelper.GetBlobContainer();
CloudBlockBlob blockBlob = container.GetBlockBlobReference(documentName);
public class FilesService
{
public async Task<string> UploadFiles(HttpContent httpContent)
{
var documentName = Guid.NewGuid().ToString();
CloudBlobContainer container = BlobHelper.GetBlobContainer();
CloudBlockBlob blockBlob = container.GetBlockBlobReference(documentName);
using (var fileStream = System.IO.File.OpenRead(#"path\myfile"))
{
await blockBlob.UploadFromStreamAsync(fileStream);
}
return blockBlob.Uri.ToString();
}
}
The problem is that I do not know how to get the path to my file (it is uploaded by the user).
When I try this:
var rootpath = HttpContext.Current.Server.MapPath("~/App_Data");
var streamProvider = new MultipartFileStreamProvider(rootpath);
await httpContent.ReadAsMultipartAsync(streamProvider);
foreach (var file in streamProvider.FileData)
{
var localName = file.LocalFileName;
using (var fileStream = System.IO.File.OpenRead(file.LocalFileName))
{
await blockBlob.UploadFromStreamAsync(fileStream);
}
}
And when I try a post request. The request just crashes and does not return anything (even an exception);
Solution:
The issue was resolved in the following way. I used a service method in order to be able to upload a collection of files.
In the BlobHelper class I save the needed information about the container and then instantiate it, it is a static class. Using a collection makes it possible to upload a multiple files as a part of the same stream.
I think you are trying to get the path to the file that is being uploaded to the Blob Storage using standard ASP.NET methods and local context. Files uploaded to the blob will not be accessible that way.
Seems like you upload your blob properly. Now, if your file uploaded successfully, your method should return blockBlob.Uri.ToString(), which is the link to your file - you may store it somewhere in the database or anywhere else.
How to connect couchDB with ASP.NET C# application? If any one can you give a sample application.
I had the same need and after evaluating the options available, to meet the requirements of my application, I created any components that helped me a lot and maybe they can help you and also others. I make it clear that I have no intention of promoting myself here, just sharing something that may be useful.
The detailed explanation of how to configure and use it is on Github.
Link: Nuget Package |
Github
Example of use for retrieving documents with mango-querie:
IList<User> users;
var sts = new List<String> { "ACTIVE", "LOCKED" };
using (UserRepository db = new UserRepository())
{
var query = db.FindOf("list-status", new { id = "OwnerIdloop.user.7", statuses = sts });
users = db.List<User>(query);
}
Array.ForEach(users.ToArray(), Console.WriteLine);
Example of adding documents:
User user = createUser("email#email.com");
using (UserRepository db = new UserRepository())
{
var result = db.Insert<User>(user); // add document and return instance changed with operation revision id
Console.WriteLine(result.Revision);
}
Example of changing documents:
using (UserRepository db = new UserRepository())
{
// Load document data by ID
var user = db.Get<User>("email#email.com");
user.Name = user.Name + "::CHANGED";
var result = db.Update<User>(user); // update document and return instance changed with operation revision id
Console.WriteLine(result.Revision);
}
Example of deleting documents:
using (UserRepository db = new UserRepository())
{
// Load document data by ID
var user = db.Get<User>("email#email.com");
var result = db.Delete<User>(user); // delete document from database. Return true case sucess or false case not deleted
Console.WriteLine($"Sucesso: {result}");
}
After installing the NuGet, just create an instance of MyCouch.Client and pass it the URL of your database.
using (var client = new MyCouchClient("http://127.0.0.1:5984/test"))
{
//Consume here
}
The format is: {scheme}://[{username}:{password}]/{authority}/{localpath}. From v0.11.0, there's a specific MyCouchUriBuilder that you can use for building the Uri. It will automatically e.g. apply Uri.EscapeDataString to username and password when calling SetBasicCredentials.
var uriBuilder = new MyCouchUriBuilder("http://localhost:5984/")
.SetDbName(TestConstants.TestDbName)
.SetBasicCredentials("foob#r", "p#ssword");
return new MyCouchClient(uriBuilder.Build());
For more details Click Here