DotVVM - Upload Files Using FileUpload Control

In this post I will show you how it is so easy in DotVVM to upload files to a local folder or even to a blob container in your Azure Storage Account using FileUpload control.
 

Uploading files to Local storage

  1. Create Empty DotVVM web project in Visual Studio.

  2. Open DotvvmStartup.cs file and add the following line to ConfigureServices methods if it does not exist.
    1. options.AddDefaultTempStorages("temp");    
    This line is telling DotVVM to set the the default temporary storage to _temp_ folder. Once you try to upload any file DotVVM will create that folder in the root directory of your application.
     
  3. Open ViewModels/DefaultViewModel file and replace its contents with the following code.
    1. using DotVVM.Framework.Controls;    
    2. ....    
    3. namespace DotVVMUploader.ViewModels    
    4. {    
    5.    public class DefaultViewModel : MasterPageViewModel    
    6.    {    
    7.       public string Title { getset; }    
    8.       public UploadedFilesCollection FilesCollection { getset; }    
    9.       public DefaultViewModel()    
    10.       {    
    11.          Title = "Welcome to upload files sample";    
    12.          FilesCollection = new UploadedFilesCollection();    
    13.       }    
    14.    }    
    15. }  
    We defined FilesCollection property as UploadedFilesCollection. This property will contain our uploaded files.
     
  4. Open Views/Default.dothtml file and add the following code.
    1. <dot:FileUpload UploadedFiles="{value: FilesCollection}"    
    2.                 AllowMultipleFiles="true"    
    3.                 AllowedFileTypes=".png,.jpg"    
    4.                 SuccessMessageText="Uploaded"    
    5.                 UploadButtonText="Select Files to Upload">  
    6. </dot:FileUpload>   
    Here, we are adding _FileUpload_ control and setting its properties as follows,

    • UploadFiles : set to FilesCollection collection we have defined in the ViewModel class.
    • AllowMultipleFiles : set to true to be able to upload many files at once.
    • AllowedFileTypes : set to restrict the file types you allow user to upload.
    • SuccessMessageText : the message you want to display in the page to inform the user that the upload is finished with no error.
    • UploadButtonText : the text you want to display as a text for upload button.

    By default DotVVM will save your file with .tmp extension and keep it for 30 minutes then will be deleted automatically.

  5. To save your files to a permanent location/storage you need to do that by yourself.

    In the FileUpload control markup will set UploadCompleted attribute with the name of the event that will be triggered once the upload is completed.
    1. <dot:FileUpload UploadedFiles="{value: FilesCollection}"    
    2.                 AllowMultipleFiles="true"    
    3.                 AllowedFileTypes=".png,.jpg"    
    4.                 SuccessMessageText="Uploaded"    
    5.                 UploadButtonText="Select Files to Upload"    
    6.                 UploadCompleted="{command: SaveMyFilesLocally()}">  
    7. </dot:FileUpload>   
  6. You need to inject IUploadedFileStorage to DefaultViewModel class.
    1. private readonly IUploadedFileStorage _uploadedFileStorage;    
    2. ...    
    3. public DefaultViewModel(IUploadedFileStorage uploadedFileStorage)    
    4. {    
    5.    _uploadedFileStorage = uploadedFileStorage;    
    6. }   
And here SaveMyFilesLocally() method that we added in FileUpload markup.
  1. public void SaveMyFilesLocally()    
  2. {    
  3.    if (!FilesCollection.IsBusy)    
  4.    {    
  5.       var permenentPath = Path.Combine(Context.Configuration.ApplicationPhysicalPath, "ProcessedFiles");    
  6.       if (!Directory.Exists(permenentPath))    
  7.       {    
  8.          Directory.CreateDirectory(permenentPath);    
  9.       }    
  10.       foreach (var file in FilesCollection.Files)    
  11.       {    
  12.          var newFileName = $"{Path.GetFileNameWithoutExtension(file.FileName)}_{file.FileId}{Path.GetExtension(file.FileName)}";    
  13.          var filePath = Path.Combine(permenentPath, newFileName);    
  14.          _uploadedFileStorage.SaveAs(file.FileId, filePath);    
  15.          _uploadedFileStorage.DeleteFile(file.FileId);    
  16.       }    
  17.       FilesCollection.Clear();    
  18.    }    
  19. }   
  • First we check if _FilesCollection_ is busy with uploading files. If not, we start to process our uploaded files by looping over _Files_ property of our _FilesCollection_.
  • After saving our file to permanent storage we delete it from the temp folder. Deleting files from temp folder is not necessary as DotVVM will delete it after 30 minutes but it is good to do to specially if your application upload huge number of files.
  • Then we clear our _FilesCollection_ to not process the same files again if we uploaded another set of files.
Here is how our sample page looks,
 
 
Uploading files to Azure Storage Account.
 
Here the magic of DotVVM begins. If at any point of time you decided to upload your file to the Azure Storage Account instead of local storage, all you need is to modify SaveMyFilesLocally method.
 
For demonstration purposes we will add a new method SaveMyFilesToAzure and let FileUpload point to it.
  1. <dot:FileUpload UploadedFiles="{value: FilesCollection}"    
  2.                 AllowMultipleFiles="true"    
  3.                 AllowedFileTypes=".png,.jpg"    
  4.                 SuccessMessageText="Uploaded"    
  5.                 UploadButtonText="Select Files to Upload"    
  6.                 UploadCompleted="{command: SaveMyFilesToAzure()}">  
  7. </dot:FileUpload>   
  1. Install WindowsAzure.Storage nuget package
    1. Install-Package WindowsAzure.Storage   
  2. Add the following using statement to DefaultViewModel class.
    1. using Microsoft.WindowsAzure.Storage;    
  3. Add SaveMyFilesToAzure method to DefaultViewModel class
    1. public async Task SaveMyFilesToAzure()    
    2. {    
    3.    if (!FilesCollection.IsBusy)    
    4.    {    
    5.       var stoageAccount = CloudStorageAccount.DevelopmentStorageAccount;    
    6.       var blobStorageClient = stoageAccount.CreateCloudBlobClient();    
    7.       var container = blobStorageClient.GetContainerReference("dotvvmblobcontainer");    
    8.       await container.CreateIfNotExistsAsync();    
    9.       foreach (var file in FilesCollection.Files)    
    10.       {    
    11.          var newFileName = $"{Path.GetFileNameWithoutExtension(file.FileName)}_{file.FileId}{Path.GetExtension(file.FileName)}";    
    12.          var blobRef = container.GetBlockBlobReference(newFileName);    
    13.          await blobRef.UploadFromFileAsync($"temp/uploadedFiles/{file.FileId}.tmp");    
    14.       }    
    15.       FilesCollection.Clear();    
    16.    }    
    17. }   
    As you see it is almost the same as before. We are  just creating a client to Azure Storage Account.

    Here I'm using the Storage Account Emulator. Explaining how to use it is out of the scope of this article. You can refer to Microsoft Documentations for more details.

Summary

 
In this post we demonstrated how it is pretty easy to upload files with DotVVM FileUpload Control to your local storage and to your Azure Blob Container.
 
You can find the full code on Github.