Azure Blob connection string containing key with + chars fails
If the key in a connection string for an Azure Blob Storage account contains a + character, the method AzureBlobStorageWithSharedKey fails with the message "Invalid length for a Base-64 char array or string."
I'm using Storage.Net 9.2.6
My rough guess is that the + characters are replaced with spaces somewhere (maybe there is some URL decoding).
~~Workaround (until fixed): Regenerate the key until you get one without a +.~~
Workaround/Fix: always URL-encode your storage key.
Stack Trace:
System.FormatException: Invalid length for a Base-64 char array or string.
at System.Convert.FromBase64_Decode(Char* startInputPtr, Int32 inputLength, Byte* startDestPtr, Int32 destLength)
at System.Convert.FromBase64CharPtr(Char* inputPtr, Int32 inputLength)
at System.Convert.FromBase64String(String s)
at Storage.Net.Factory.AzureBlobStorageWithSharedKey(IBlobStorageFactory factory, String accountName, String key, Uri serviceUri)
at Storage.Net.Microsoft.Azure.Storage.Blobs.Module.CreateBlobStorage(StorageConnectionString connectionString)
at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
at Storage.Net.ConnectionString.ConnectionStringFactory.Create[TInstance](String connectionString, Func`3 createAction)
As I expected the + is replaced by a space in StorageConnectionString.Parse() with the line
_parts[key] = value.UrlDecode();
which leaves me uncertain if this is a bug or a feature.
On one hand, it is formatted like a URI, starting with the storage type as "protocol". So one could argue UrlDecodeing the arguments is a valid thing to do.
On the other hand it is really unexpected for me as a user that I cannot just copy&paste the storage key into the connection string but have to check for characters which need URL encoding, even if its just a connection string, not an actual URL.
I'm facing the same issue. The workaround is like playing roulette...
This is unfortunate, yes plus sign in URL has a special meaning - space. We think of all the parameters as URL-encoded, because in some cases like drive path there are special characters that cause issues with a parser. The safest way to pass parameters is to url-encode them first though.
Yes, this is a bit unfortunate. It is inconsistent with how DB connection strings work, for example. But I understand, why it is necessary to url-encode the parameters.
It would be great though if this is mentioned in the documentation. I would add this as a hint to every occurrence of a connection string in the documentation, but I know this seems a bit excessive.
Workaround (until fixed): Regenerate the key until you get one without a
+.
The workaround is like playing roulette...
Maybe instead of "key roulette" you could (strictly a workaround) use %2B instead of +
Yeah, should have updated the workaround after finding out the reason it doesn't work with a +. Have done it now.
@aloneguid should the connection string be encoded within the StorageNet library, or encoding it before initializing the storage would be the right way to do it?