Using Azure Blobs with Azure Website - azure

I'm in the process of making an MVC Windows Azure website which involves users uploading images.
I wanted to store the images in blobs.
I searched for tutorials but most of them deal with Webapps rather than MVC websites.
The only useful tutorial I found was: http://www.codeproject.com/Articles/490178/How-to-Use-Azure-Blob-Storage-with-Azure-Web-Sites
I'm new to the whole MVC/Windows Azure/Visual Studio scene and I got confused at Step 7 where I had to connect to Cloud Storage Account.
var storageAccount = CloudStorageAccount.Parse(
ConfigurationManager.ConnectionStrings["StorageConnection"].ConnectionString);
I can't figure out where I'm supposed to put that bit of a code.
Same for the code in Step 8: Creating a container
blobStorage = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobStorage.GetContainerReference("productimages");
if (container.CreateIfNotExist())
{
// configure container for public access
var permissions = container.GetPermissions();
permissions.PublicAccess = BlobContainerPublicAccessType.Container;
container.SetPermissions(permissions);
}
And Step 9: Save the Image to a BLOB
string uniqueBlobName = string.Format("productimages/image_{0}{1}",
Guid.NewGuid().ToString(), Path.GetExtension(image.FileName));
CloudBlockBlob blob = blobStorage.GetBlockBlobReference(uniqueBlobName);
blob.Properties.ContentType = image.ContentType;
blob.UploadFromStream(image.InputStream);
Any help will be really appreciated. Any other links to relevant tutorials are also welcome.
Thanks a lot!

I assume you've added the Windows Azure Storage NuGet package to your Web App project? That didn't seem explicit in the reference you quoted, but if you hadn't you'd be seeing a bunch of unresolved compiler errors.
In terms of where the code goes, it's rather up to you. The assignment to storageAccount is like setting a database connection string; nothing is going across the wire, so you could set it once perhaps and make it available throughout your application as part of some static class instance.
In terms of creating a container, you'd do this whenever you want to store data - consider it tantamount to creating a folder in a file system or maybe a table in a relational database. If your application is always storing information in the same "hard-coded" container, you could set your container up ahead of time in the portal and not create in code.
Putting code like this in though provides a bit of resiliency in case the container got deleted through some external process; the same way that an app using SQL Server could check for the existence of an Employee table before doing updates/retrieves, since it's possible (but not likely) someone deleted the Employee table via some other SQL tool.
Saving the image to the blob would be put directly behind whatever controller is responsible for initiating that action. This is where you're doing the 'real' work. The code in your sample specifically references a container productimages, so it could be immediately preceded by the code in Step 8 if you wanted to be certain that there no chance the container was deleted (through the portal, for instance). Again, that would be similar to checking for the existence of a database table in traditional client/server code everytime you accessed data in it (which most of us might consider overkill and we'd resort to exception handling to cover that contingency).

Old question but still may help noobs!
Azure Webapps do accept MVC apps. Webapps on Azure are just a container which Im sure can take different types of ASP.NET based applications, Forms or MVC, C# or VB.net.
Assuming you know the basics of an MVC application you can just create the Azure Webapp and publish it to there. It's as straight forward as that.
This code:
var storageAccount = CloudStorageAccount.Parse(
ConfigurationManager.ConnectionStrings["StorageConnection"].ConnectionString);
And this:
blobStorage = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobStorage.GetContainerReference("productimages");
if (container.CreateIfNotExist())
{
// configure container for public access
var permissions = container.GetPermissions();
permissions.PublicAccess = BlobContainerPublicAccessType.Container;
container.SetPermissions(permissions);
}
Can go in a new class specifically for Blob services e.g. call it something like blobServices.cs and save it in the root of your MVC app and it can look like so:
var storageAccount = CloudStorageAccount.Parse(
ConfigurationManager.ConnectionStrings["StorageConnection"].ConnectionString);
blobStorage = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobStorage.GetContainerReference("productimages");
if (container.CreateIfNotExist())
{
// configure container for public access
var permissions = container.GetPermissions();
permissions.PublicAccess = BlobContainerPublicAccessType.Container;
container.SetPermissions(permissions);
}
Which is probably the best practice. From there on in the Controller/s of your MVC app you can do something like this:
namespace blabla.cs
{
public controller myBlobController
{
//instantiate the blob service
BlobProfileImageServices _blobServices = new BlobProfileImageServices();
public public ActionResult Index()
{
//call your blob storage service
//and loop through each blob
CloudBlobContainer blobContainer = _blobServices.GetCloudBlobContainer();
List<string> blobs = new List<string>();
foreach (var blobItem in blobContainer.ListBlobs())
{
blobs.Add(blobItem.Uri.ToString());
}
}
}
}

Related

How does Azure BlobStorage connection data have to be stored to support all available addressing modes?

I am using libraries Microsoft.Azure.Storage.Blob 11.2.3.0 and Microsoft.Azure.Storage.Common 11.2.3.0 to connect to an Azure BlobStorage from a .NET Core 3.1 application.
Users of my application are supposed to supply connection information to an Azure BlobStorage to/from where the application will deposit/retrieve data.
Initially, I had assumed allowing users to specify a connection string and a custom blob container name (as an optional override of the default) would be sufficient. I could simply stuff that connection string into the CloudStorageAccount.Parse method and get back a storage account instance to call CreateBlobCloudClient on.
Now that I'm trying to use this method to connect using a container-specific SAS (also see my other question about that), it appears that the connection string might not be the most universal way to go.
Instead, it now seems a blob container URL, plus a SAS token or an account key (and possibly an account name, thought that seems to be included in the blob container URL already) are more versatile. However, I am concerned that the next way of pointing to a blob storage that I need to support (whichever that may be) might require yet another kind of information - hence my question:
What set of "fields" do I need to support in the configuration files of my application to make sure my users can point to their BlobStorage whichever way they want, as long as they have a BlobStorage?
(Is there maybe even a standard solution or best practice recommendation by Microsoft?)
Please note that I am exclusively concerned with what to store. An arbitrarily long string? A complex object of sorts? If so, with what fields?
I am not asking how to store that configuration once I know what it must comprise. For example, this is not about securely encrypting credentials etc.
On Workaround To access the Storage account using the SAS Token you need to pass the Account Name along with the SAS Token and Blob Name if you trying to upload and You need give the permission for your SAS Token .
Microsoft recommends using Azure Active Directory (Azure AD) to authorize requests against blob and queue data if possible, instead of Shared Key. Azure AD provides superior security and ease of use over Shared Key. For more information about authorizing access to data with Azure AD, see Authorize access to Azure blobs and queues using Azure Active Directory..
Note: Based on my testes you need to pass the Storage Account Name And SAS Token and the Container Name And Blob name
Example: I tried with uploading file to container using container level SAS Token . able to upload the file successfully.
const string sasToken = "SAS Token";
StorageCredentials storageCredentials = new StorageCredentials(sasToken);
const string accountName = "teststorage65";//Account Name
const string blobContainerName = "test";
const string blobName = "test.txt";
const string myFileLocation = #"Local Path ";
var storageAccount = new CloudStorageAccount(storageCredentials, accountName, null, true);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer blobContainer = blobClient.GetContainerReference(blobContainerName);
//blobContainer.CreateIfNotExists();
CloudBlockBlob cloudBlob = blobContainer.GetBlockBlobReference(blobName);
cloudBlob.UploadFromFile(myFileLocation);
As you already know You can use the Storage connection string to connect with Storage.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("Connection string");
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("test");
Your application needs to access the connection string at runtime to authorize requests made to Azure Storage.
You have several options for storing your connection string Or SAS Token
1) You can store your connection string in an environment variable.
2) An application running on the desktop or on a device can store the connection string in an app.config or web.config file. Add the connection string to the AppSettings section in these files.
3) An application running in an Azure cloud service can store the connection string in the Azure service configuration schema (.cscfg) file. Add the connection string to the ConfigurationSettings section of the service configuration file.
Reference: https://learn.microsoft.com/en-us/azure/storage/common/storage-configure-connection-string

Application Settings Azure

i'm new to azure and i have the following issue:
i have this key in my web.config:
add key="BlobStorageConnectionString" value="xxxxxxxx"
The thing is when i add it to app settings in azure app service, when i search in the logs i get this:
Getting "BlobStorageConnectionString" from ServiceRuntime: FAIL
Getting "BlobStorageConnectionString" from ConfigurationManager: PASS.
i've already tried a few tutorials, but i still can't find a reason.
I'm running out of ideas, any suggestions?
If you add the Storage Account string in the Application Settings, it will be stored as an environment.So you could read it with Environment.GetEnvironmentVariable("storageconnectionstring").
Then parse it the code will be like below shows.
string storageConnectionString = Environment.GetEnvironmentVariable("storageconnectionstring");
// Check whether the connection string can be parsed.
if (CloudStorageAccount.TryParse(storageConnectionString, out storageAccount))
{
try
{
// Create the CloudBlobClient that represents the Blob storage endpoint for the storage account.
CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();
........
........
}
}
And you could also configure your connection in your app like WebJob, you could use JobHostConfiguration(). And the code would be like this.And the connection name should be AzureWebJobsStorage.
var config = new JobHostConfiguration();
config.DashboardConnectionString = "";
Also you could choose to use Configuration Classes,about the details you could refer to this article.
Hope this could help you, if you still have other questions,please let me know.

Error on azure web app deployment

I am new in azure application development. As per the requirements given to me, I had developed an application on azure and successfully deployed it on azure cloud.Blob storage was also being used in that application. Everything was working fine.
When I was deploying it on cloud then that time I was not very much aware about azure deployment so I had deployed it as a cloud service. It worked fine but the only issue was about slow loading at the very first time. Then after doing lot of research I found some solutions so I have deployed it as web app then the slow loading problem was resolved. But with web app deployment, I am facing another problem with a single page which is using blob storage. Below is the error I am getting when opening that specific page :
Below is the code which I had written :
public List<string> ListContainer()
{
List<string> blobs = new List<string>();
if (!Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.IsAvailable) return null;
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.GetConfigurationSettingValue("FileStorageAccount"));
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
IEnumerable<CloudBlobContainer> containers = blobClient.ListContainers();
foreach (CloudBlobContainer item in containers)
{
foreach (IListBlobItem blob in item.ListBlobs())
{
blobs.Add(string.Format("{0}", blob.Uri));
}
}
return blobs;
}
It is working fine when running on visual studio but on deployment If I am going with cloud service deployment then I am not getting this specific error. Other pages are working fine with web deployment. The page which causing an error uses blob storage.
I had done lot of research but no luck. Please help!!!
I suspect you have not defined the "FileStorageAccount" Setting in the CSCFG file. Try using the CloudConfigurationManager.GetSetting method. It will read configuration values from the web.config or service configuration file. See also https://stackoverflow.com/a/19643516/5382426.

Saving an X509 certificate from an Azure Blob and using it in an Azure website

I have an Azure Website and an Azure Blob that I'm using to store a .cer X509 certificate file.
The goal is to get the .cer file from the blob and use it to perform an operation (the code for that is in the Controller for my Azure website and it works).
When I run the code locally (without publishing my site) it works, because I save it in D:\
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnectionString"]);
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve reference to a previously created container.
CloudBlobContainer container = blobClient.GetContainerReference("myContainer");
// Retrieve reference to a blob named "testcert.cer".
CloudBlockBlob blockBlob = container.GetBlockBlobReference("testcert.cer");
// Save blob contents to a file.
using (var fileStream = System.IO.File.OpenWrite("D:/testcert.cer"))
{
blockBlob.DownloadToStream(fileStream);
}
**string certLocation = "D:/testcert.cer";
X509Certificate2 myCert = new X509Certificate2();
myCert.Import(certLocation);**
I am unable to figure out how/where I can save it. If I try and use the Import method but enter a url (that of the Azure blob where the certificate is stored) I get an error because Import can't handle urls.
Any idea what I can use as temp storage on the Azure website or in the blob and create an X509Certificate from it?
Edit: I'm trying to add more detail about the problem I'm trying to solve.
Get a cert file from an Azure blob and write it to an Azure website.
Use the .Import(string pathToCert) on an X509Certificate object to create the cert which will be used to make a call in a method I've written in my controller.
I've been able to work around 1 by manually adding the .cer file to the wwwroot folder of my site via FTP. But now when I use Server.MapPath("~/testcert.cer"); to get the path for my certificate I get this: D:\home\site\wwwroot\testcert.cer
Obviously when the Import method uses the string above as a path once it's deployed to my azure website, it's not a valid path and so my cert creation fails.
Any ideas? Thanks!
Saving the certificate locally is generally a no-no for Azure, you've got BlobStorage for that.
Use the Import(byte[]) overload to keep and load the certificate in memory. Here's a quick hand coded attempt...
// Used to store the certificate data
byte[] certData;
// Save blob contents to a memorystream.
using (var stream = new MemoryStream())
{
blockBlob.DownloadToStream(stream);
certData = stream.ToArray();
}
X509Certificate2 myCert = new X509Certificate2();
// Import from the byte array
myCert.Import(certData);
Very simple. And the answer covers all and any web hosters, not just Azure.
First of all, I would highly recommend that you never statically put a path to a folder in your Web Projects! Then what you can do is:
User the Server.MapPath("~/certs") method to obtain the physical path of a certs folder within your web site root folder.
Make Sure that no one can access this folder from the outside world:
By adding this additional location section in your web.config you are blocking any external access to this folder. Please note that locationelement has to be direct descendant of the root configuration element in your web.config file.
UPDATE with non-azure relevant part on how to write file to local file system of a ASP.NET web project:
var path = Server.MapPath("~/certs");
using (var fileStream = System.IO.File.OpenWrite(path + "\testcert.cer"))
{
// here use the fileStream to write
}
And a complete sample code on how to use Blob Stroage client to write content of a blob to a local file:
var path = Server.MapPath("~/certs");
using (var fileStream = System.IO.File.OpenWrite(path + "\testcert.cer"))
{
blockBlob.DownloadToStream(fileStream );
}
But, #SeanCocteau has a good point and much simpler approach - just use MemoryStream instead!
You can now upload your certificates via the Portal, add an app setting to your site, and have the certificate show up in your site's Certificate Store.
See this blog post for more details:
http://azure.microsoft.com/blog/2014/10/27/using-certificates-in-azure-websites-applications/

How to connect Azure blob storage through website MVC4

I develop a website on Windows Azure, MVC4. I try to upload and get photos from blobs.
My related code (that I got from other examples on web):
var storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["StorageConnection"].ConnectionString);
var blobStorage = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobStorage.GetContainerReference("abc");
container.CreateIfNotExists();
var permissions = container.GetPermissions();
permissions.PublicAccess = BlobContainerPublicAccessType.Container;
container.SetPermissions(permissions);
My related web.config code:
<add name="StorageConnection" connectionString="DefaultEndPointsProtocol=https;AccountName=abc;AccountKey=*******"/>
When I run I got a format exception. Please note that it is web site.
As per some posts, when I put my connection string to app.config, no solution.
Thank you very much for any assistance.
You shall not use connectionStrings section to store Azure Storage Connection string!
Use appSettings instead and you will have no issues. It is confusion that the Storage credentials is also named "Connection string", but it has nothing to do with the connectionStrings section in your configuration file. connectionStrings section is intended solely for use DataBase connection strings.

Resources