How can I configure Orchard to use BLOB Storage on Azure after deployment?

Topics: Administration, Installing Orchard
Jul 20, 2012 at 10:32 PM

I deployed Orchard to Azure using the Gallery within the new Azure Preview site. I want to upload a 400MB file for authenticated users to download. I linked my storage account, but it looks like the site is storing stuff directly in /site/wwwroot/Media/Default. I have read Deploying Orchard to Windows Azure, but it does not say anything about configuring the Media module to use the linked storage account. Can you point me to the docs on that, if it is even possible to do after deployment?

Thanks, and thanks for the great product.

Coordinator
Jul 21, 2012 at 1:02 AM

If you use the Azure Website and the associated gallery package then it's making use of teh file system. To use the Blob storage you will need the Azure package you can download from the orchard.codeplex.com website, or the source code directly, which contains the Media module using Blob storage. Usually you would go on the Cloud services instead of the Azure Web Services, though I am sure you can mix them. We have never tried that but if you know Azure correctly and with some Orchard guidance it should be pretty easy.

Jul 21, 2012 at 11:58 AM

Hi Sebastienros. Thanks for replying so quickly.

So you're saying I have to recompile rather than reconfigure. I accept that reality and will give it another shot, but I am interested in what went in to that thinking. Did Orchard developers find it impossible to design the code with the "abstracted file system" and just inject the one that uses BLOB storage or is it more a matter of how the Azure Website gallery works, that the 1.4.2 distribution the gallery installs does not contain the BLOB bits? I am curious about the design issue of the difficulty of designing an app that works in a traditional hosted solution/file-system and an app that uses Azure BLOB storage.

I did try those Deploying Orchard to Windows Azure instructions in which I compiled on ClickToBuildAzurePackage.cmd, but the Azure Web Site preview failed when I gave it the package. I guess I can cross my fingers and try again on the non-preview site using Azure Web Services. Wish me luck.

Coordinator
Jul 21, 2012 at 5:01 PM

The Azure package is for Azure Cloud Services. You can't use it for Azure Web Sites. If you still want blobs in Azure web sites you need to add the specific Media module from the Azure solution. Also take a look at /Config/HostComponents.config when you can see how to inject configuration parameters. 

I will be able to help you more later by providing some detailed documentation for this scenario and more about Azure Web Sites, but only in a few days.

Jul 21, 2012 at 5:14 PM

Thanks, I am looking forward to more documentation on deploying to Azure Web Sites.

I'm concerned about the statement "you need to add the specific Media module from the Azure solution." Are you saying it still won't use blob storage if I follow these instructions and deploy to Azure Cloud Services? I think I need to use blob storage. 

Coordinator
Jul 21, 2012 at 5:26 PM

Blog storage is a module from the Azure specific project in Orchard, intended for Cloud Services at first. It's possible to use blob with Azure Web Sites but there is no documentation as of today for Orchard. 

Jul 21, 2012 at 10:58 PM

Great. After following the same directions for Azure Cloud Services, I get the "Could not load file or assembly 'msshrtmi' or one of its dependencies. An attempt was made to load a program with an incorrect format." I built it on a 32-bit dev machine, but all I did was run the .CMD file. StackOverflow says I should edit the CSPROJ, but which one for Orchard? Oy vey.

Jul 21, 2012 at 11:26 PM

Edited and rebuilding now, but it seems to be building for DEBUG. That seems odd.

Jul 24, 2012 at 1:22 PM

Doesn't work. I guess I am going to have to shelve using Orchard on Azure with Blob storage until I setup a 64bit dev machine. Unless the Orchard team makes such a build available. Do you?

Mar 16, 2013 at 10:41 PM
Edited Mar 16, 2013 at 10:45 PM
Here are the steps to store the media in Azure Blob storage (also works from a local site, no need for an Azure Website)

Add the Orchard.Azure project to your existing project.
Add a reference from the Orchard.Web project to the Orchard.Azure project.
Copy sites.config from Orchard.Azure.Web to Orchard.Web
Add an app settingskey to the web.config (local project) or the Configure -> AppSetting in for your azure Web site:
<appSettings>  
    <add key="DataConnectionString" value="DefaultEndpointsProtocol=http;AccountName=youraccount;AccountKey=yourkey"/>
  </appSettings>
In the Orchard.Azure project change these lines in their own file (change 4 files):
      public AzureShellSettingsManager(IShellSettingsManagerEventHandler events)
            : this(CloudStorageAccount.Parse(ConfigurationManager.AppSettings["DataConnectionString"]), events) {}
 public AzureBlobStorageProvider(ShellSettings shellSettings)
            : this(shellSettings, CloudStorageAccount.Parse(ConfigurationManager.AppSettings["DataConnectionString"])) {
        }
  public AzureFileSystem(string containerName, string root, bool isPrivate)
            : this(containerName, root, isPrivate, CloudStorageAccount.Parse(ConfigurationManager.AppSettings["DataConnectionString"])) {
        }
public HttpContextWeaver()
        {
            _current = HttpContext.Current;
        }
If you have a storage account with a custom domain name, add this to the storage connection string:
    <add key="DataConnectionString" value="BlobEndpoint=http://blob.yourdomain.com/;DefaultEndpointsProtocol=http;AccountName=youraccount;AccountKey=yourkey"/>
  </appSettings>
Mar 17, 2013 at 2:06 AM
Edited Mar 17, 2013 at 10:31 AM
What do you mean "change these lines in their own file" ?

Nevermind... now I see. The existing code uses RoleEnvironment.GetConfigurationSettingValue to retrieve the value from the service configuration, but the changes above instead grab it from the web.config.
Mar 17, 2013 at 11:07 AM
This worked great for me! I have a custom domain setup on my blob storage and can access the files just fine, but when I add in the BlobEndpoint property, it doesn't work and throws a 400 request. Any ideas?
Mar 17, 2013 at 11:42 AM
You are right, the Azure Cloud Services use the RoleEnvironment.GetConfigurationSettingValue , and the Azure Websites use the ConfigurationManager.AppSettings.

I used the 1.x branch (haven't tested with the 1.6 release)

In the Orchard.Azure, AzureFileSystem.cs there is this line:
     _absoluteRoot = Combine(Combine(_storageAccount.BlobEndpoint.AbsoluteUri, containerName), root);
Place a breakpoint there, it should use the BlobEndpoint from the connectionstring.
Jul 2, 2013 at 9:17 PM
A nicer way is to add a reference to Microsoft.WindowsAzure.Configuration.dll (azure 2.0 sdk)

Now we can add this:
CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"))
This will make sure that the right location is searched, web.config for normal projects, or the .cscfg file for azure, so no more worries where your project is started.

I totally removed the HttpContextWeaver from all locations and it seems to work.
Coordinator
Jul 2, 2013 at 9:41 PM
Erik, could you share your changes as a pull request or a patch ?
Are you working on 1.x ?
Jul 3, 2013 at 9:07 PM
I'm working on 1.x
But run into problems when testing this on azure: http://orchard.codeplex.com/workitem/19831

(and some more problems setting up mercurial and other stuff, like the unit tests not working either)
Aug 24, 2013 at 8:50 PM
This is implemented in 1.x in changeset 6bd43591ac66

Now the blob storage is useable in every project (azure PaaS, VM, Website and non azure as well)
Oct 9, 2013 at 11:40 AM
Erik-
Fantastic work making this a core feature. Is there a way in the connection string to specify a custom domain that you want to be used in making links to resources? For instance, I have a blob aciassets & and I add an image, I get http://aciassets.blob.core.windows.net/media/Default/Me/HeadshotBW.gif but I also have a custom domain setup for assets.andrewconnell.com that is pointing to that storage blob, and as such, this works: http://assets.andrewconnell.com/media/Default/Me/HeadshotBW.gif

I'd much rather use the latter link for branding purposes. Looking at this page (http://msdn.microsoft.com/en-us/library/windowsazure/ee758697.aspx) it appears I should be able to just prefix the connection string with BlobEndpoint=assets.andrewconnell.com; but that isn't working.

So for now, while I can use the storage bucket for my blobs, after uploading & referencing media within a page/article, I then have to manually go in and edit the HTML for the link to the blob.
Oct 9, 2013 at 12:26 PM
Did you try: BlobEndpoint=http://assets.andrewconnell.com/

add the http:// part to it?
I will try this later to see if it is broken
Oct 9, 2013 at 1:48 PM
No I didn't, but that works (without the trailing "/" on the URL). Works great for new references. Existing references don't get updated (which makes sense as content stores the link, not a reference).