Recently we came across the need to store files in a CDN instead of common file shares like SkyDrive or DropBox. There are multiple cloud service providers who provide this service; Amazon S3 and Azure Storage being two of the prominent ones. At the time we manually uploaded files via the management console and distributed the links to the files ad hoc.
But in a real life application, we would be utilizing Storage for storing user files like Image, videos, mp3s and serving them up through a nice content management portal. So today, we will see how to build an ASP.NET MVC application that uploads files to Azure Cloud Storage, get the list of items in storage and have a rudimentary view of the files.
Usually Azure Projects imply testing out online in Azure portal, but for Storage, we have a nice Emulator that we can run locally and test our complete application out. Once tested, we can move to Azure Cloud.
The MVC Application
Pre-Requisites
Before we get started, we need to have the Azure SDK installed on the Client. You can install the client using Web Platform Installer as shown below
Once you have the Azure SDK setup, we can get started.
The Application Template
Step 1: We will start off with a new MVC 4 application and use the Basic Template.
Step 2: Once the project is setup, we will have to get the Azure Storage client libraries. We can get it using the Nuget Package Management Dialog. As seen below, we did a search for ‘azure storage’ in the ‘Online’ node.
Step 3: Select ‘Windows Azure Storage’ and Install. This will kick off the dependency checker which will resolve all the required dependencies.
Step 4: Once all the dependencies are resolved, we’ll get the License Acceptance Dialog as follows.
All the components are from Microsoft, so we can safely accept and continue.
Step 5: Once the installation is done, go to the ‘Updates’ node and update all the Azure related components. Once the updates are complete, you are all set to actually get started.
Starting the Storage Emulator
Before we can use the Emulator in our application, we need to run it explicitly. In Windows 8 you can search for ‘Azure’ on the Home screen. In Windows 7 you can type ‘Azure’ in the search textbox on the start button.
Find the ‘Windows Azure Command Prompt’ and launch it.
Kick off the Storage Emulator using the command
csrun /devstore
Once the emulator starts, you’ll have a Tray Icon that you can use to shut down once you are done

Now we are all set to start building the MVC App.
Setting up the Model
Under the Models folders add two classes, CloudFile and CloudFilesModel.
The CloudFile class is as follows
public class CloudFile
{
public string FileName { get; set; }
public string URL { get; set; }
public long Size { get; set; }
public static CloudFile CreateFromIListBlobItem(IListBlobItem item)
{
if (item is CloudBlockBlob)
{
var blob = (CloudBlockBlob)item;
return new CloudFile
{
FileName = blob.Name,
URL = blob.Uri.ToString(),
Size = blob.Properties.Length
};
}
return null;
}
}
It has three properties to start off with, FileName, URL and the Size of the File. It also has a static method to convert an instance of IListBlobItem into a CloudFile.
The CloudFilesModel class acts as the container for the CloudFile instances, that it exposes through the ‘Files’ property.
public class CloudFilesModel
{
public CloudFilesModel()
: this(null)
{
Files = new List<CloudFile>();
}
public CloudFilesModel(IEnumerable<IListBlobItem> list)
{
Files = new List<CloudFile>();
if (list != null && list.Count<IListBlobItem>() > 0)
{
foreach (var item in list)
{
CloudFile info = CloudFile.CreateFromIListBlobItem(item);
if (info != null)
{
Files.Add(info);
}
}
}
}
public List<CloudFile> Files { get; set; }
}
Setting up the Connection String to connect to the Azure Blob Storage (emulator)
The client SDK depends on a connection string to connect to Cloud Storage. We’ll save the connection information in Web.config’s AppSettings so that once our testing is done, we can flip it to the Actual connection string in production.
We need to add an App Setting called StorageConnectionString with the value set to “UseDevelopmentStorage=true”. This refers to local emulator.
The Storage Container name need not be in the Web.config because you might want to use different container names depending on the context. For example, you might use a different Container per user or per Company or similar segregations. However in our case today, we will only use one container hence we’ll add it to the Web.config using the “CloudStorageContainerReference”.
<appSettings>
… snipped …
<add key="StorageConnectionString" value="UseDevelopmentStorage=true"/>
<add key="CloudStorageContainerReference" value="dnc-demo" />
</appSettings>
Notes on Naming Conventions for Cloud Storage Continer
The Name we select for our containers need to abide by URL naming conventions. To recap these requirements:
- With the exception of the dash, no other symbols including white space are allowed.
- They must start with a lowercase letter or number.
- All letters must be lowercase. Uppercase letters are not allowed.
- They may contain a dash (-), but if a dash is used is, it must be preceded and followed by either a lowercase letter or a number.
- They must be at least three characters long.
- They can be no more than 63 characters.
If we don’t follow these guidelines, Azure throws a generic runtime Http 400 runtime error. The only hint is a message saying, one of the inputs is out of range.
The HomeController
Once the model and connection strings are setup, we create our HomeController. Use the Add New Controller dialog and select “MVC Controller with empty read/write sections”.

Keep the Index() action method and delete the rest.
Listing all Files in the container
Let’s build an Index page and the Action method that will show files in the Container. To get this, we need to retrieve the list of files from the Container and convert them into CloudFile item and store it the CloudFilesModel. The view will use the CloudFilesModel to render the items.
Controller
The Action method therefore does the following:
1. Connect to the storage Account using the Connection String -
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));
2. Create a StorageClient -
CloudBlobClient storageClient = storageAccount.CreateCloudBlobClient();
3. Create a StorageContainer from the StorageClient -
CloudBlobContainer storageContainer = storageClient.GetContainerReference(
ConfigurationManager.AppSettings.Get("CloudStorageContainerReference"));
4. Create a CloudFilesModel by passing the ListBlobs in the Container -
CloudFilesModel blobsList = new
CloudFilesModel(storageContainer.ListBlobs(useFlatBlobListing: true));
The complete listing is as follows
public ActionResult Index()
{
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));
CloudBlobClient storageClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer storageContainer = storageClient.GetContainerReference(
ConfigurationManager.AppSettings.Get("CloudStorageContainerReference"));
CloudFilesModel blobsList = new
CloudFilesModel(storageContainer.ListBlobs(useFlatBlobListing: true));
return View(blobsList);
}
View
Once the controller is ready to return the view model, we’ll go ahead and build the view. We add Index.cshtml and the following markup + razor code to simply loop through each Cloud File and add it as a list item.
At the bottom of the page, we have an Action Link that points to another Action Method called UploadFile. The final listing is as follows:
@model MvcAzureBlogStorage.Models.CloudFilesModel
@{
ViewBag.Title = "File List";
}
<h2>File List</h2>
<ul>
@foreach (var item in Model.Files)
{
<li>
<a href="@item.URL">@item.FileName</a> (@item.Size bytes)
</li>
}
</ul>
@Html.ActionLink("Upload Another File", "UploadFile")
If we run the application now, we’ll not have anything in the Index View only the “Upload Another File” link that is linked to an non-existing Action Method. Let’s fix that first.
Upload File Action
Controller
The Upload File Action method does the following
- Gets the Storage Account using the Connection String
- Create a StorageClient instance using the Account
- Retrieve the StorageContainer from the StorageClient. If the container doesn’t exist, it is created.
- Create a CloudFilesModel by passing the ListBlobs in the Container
- Then for each file in the Request get a CloudBlockBlob instance using the file name of the source file.
- Use the CloudBlockBlob to upload from the request stream.
The entire code list is as follows
public ActionResult UploadFile()
{
if (Request.Files.Count > 0)
{
CloudStorageAccount storageAccount =
CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));
var storageClient = storageAccount.CreateCloudBlobClient();
var storageContainer = storageClient.GetContainerReference(
ConfigurationManager.AppSettings.Get("CloudStorageContainerReference"));
storageContainer.CreateIfNotExists();
for (int fileNum = 0; fileNum < Request.Files.Count; fileNum++)
{
string fileName = Path.GetFileName(Request.Files[fileNum].FileName);
if (
Request.Files[fileNum] != null &&
Request.Files[fileNum].ContentLength > 0)
{
CloudBlockBlob azureBlockBlob = storageContainer.GetBlockBlobReference(fileName);
azureBlockBlob.UploadFromStream(Request.Files[fileNum].InputStream);
}
}
return RedirectToAction("Index");
}
return View("UploadFile");
}
View
The UploadFile View provides a HTML file input element and an Upload button to trigger the Upload Action method. The complete markup is as follows:
@{
ViewBag.Title = "UploadFile";
}
<h1>Upload a File</h1>
@using (Html.BeginForm("UploadFile", "Home", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
<input type="file" id="FileUploader" name="FileUploader" multiple="multiple" />
<input type="submit" name="Submit" id="Submit" value="Upload" />
}
Running the Application
Now that our controllers and views are ready, we can run the application end-to-end and add some files to the Storage Emulator.
The Index Page
On first run, the Index page is empty.

The Upload Page
We click on the ‘Upload Another File’ link to navigate to the Upload file page. We click on Browser and select a file and the click ‘Upload’ to send it to the Blob storage.

Once Upload completes, the application navigates back to the File List
Accessing the Uploaded Files
Once files have been uploaded, they get a URL and as we can see above, the files are hyperlinked to this URL. When we click the URL, we should be able to see or download the file. However if we click on the file, we are likely to see this instead:
Huh! Why?
Well, by default, the Blob Storage Containers provide no permissions for external access. This results in the 404. How to provide access?
Step 1: In Visual Studio, open the Database explorer, expand the Windows Azure Storage Note, expand the Blobs node and Select the container (dnc-demo) as shown below.
Step 2: Now bring up the properties dialog for the Blob Container. You’ll see there is a property called PublicAccess under Permissions. This is set to ‘Off’. The other options are ‘Container’ and ‘Blob’. We don’t want our entire Blob to be public, but we could have make the container public so that the files in it are visible to others. On change Azure Storage will warn you that this might take some time to take effect. In dev environment, the time is negligible but you should keep it in mind in Production.
Step 3: Now navigate back to the Index view and click on the Link for 1.jpg. As we can see below, this time we navigate to the file correctly! Sweet!
Multiple File Upload
With HTML5 compliant browsers multiple file upload is actually easier than before. All we have to do is add the multiple attribute to the input as follows
<input type="file" id="File01" name="File01" multiple="multiple" />
Now if you navigate to Upload file page and click on Browser, the file picker will allow you to select multiple files.

Click on Open and the Input is actually populated with all the file names comma separated.
Click on Upload and all the files will get uploaded and the app will navigate back to the Index
As we can see all our files were uploaded successfully.
Notes: The Multi file upload support is a little spotty across browsers. While Chrome and Firefox have been good for a bit, the above example is with IE v10. So unless you are on the latest and greatest browser, your mileage may vary with respect to Multiple File Upload.
One Big Limitation
Before we conclude grandly, it will be unfair if we didn’t put out the most obvious shortcoming in this technique. That’s the default file size limit of 4MB. This limit is imposed by IIS to prevent super large posts DOSing your server. Increasing the default limit though possible is not the desired solution. The ideal solution for this is to upload files ‘chunked’ meaning in pieces.
In the current technique, files are streamed into memory before written out to the output stream, in chunked upload files are streamed in pre-defined sized pieces (or chunks). The actual process is a little involved to start at this point. It deserves a dedicated effort for itself so I won’t go into details now. Suffice to you say that you have seen it action when you are uploading multiple files to cloud stores like SkyDrive or DropBox.
Conclusion
Now we can conclude the article with the takeaway that we saw how to upload files into Azure Blob storage. We also figured out how to setup permissions for the blob container.
Going live now is a matter of setting up our storage account in Azure and replacing the development connection string with the Production connection string!
Download the entire source code of this article (Github)
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of
DotNetCurry,
DNC Magazine for Developers,
SQLServerCurry and
DevCurry. He has also authored a couple of books
51 Recipes using jQuery with ASP.NET Controls and
The Absolutely Awesome jQuery CookBook.
Suprotim has received the prestigious Microsoft MVP award for Sixteen consecutive years. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.
Get in touch with him on Twitter @suprotimagarwal or at LinkedIn