I'm getting this error from Azure IoT Provisioning Service when creating the provisioning client.
System.ArgumentException: 'Should specify SharedAccessKeyName'
I copied the Connection String from the Portal, what could be wrong?
using System;
using System.IO;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Microsoft.Azure.Devices.Provisioning.Service;
namespace EnrollmentApp
{
class Program
{
private static string ProvisioningConnectionString = "HostName=happybeerhub-us.azure-devices.net;DeviceId=test-device-01;SharedAccessKey=tawpddfqUt3EHZg9a5tUzQ5fjros7zMhKsZbmuXzwXE=";
private static string EnrollmentGroupId = "test";
private static string X509RootCertPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @"key.pfx");
static void Main(string[] args)
{
RunSample().GetAwaiter().GetResult();
Console.WriteLine("\nHit <Enter> to exit ...");
Console.ReadLine();
}
public static async Task RunSample()
{
Console.WriteLine("Starting sample...");
using (ProvisioningServiceClient provisioningServiceClient =
ProvisioningServiceClient.CreateFromConnectionString(ProvisioningConnectionString))
{
#region Create a new enrollmentGroup config
Console.WriteLine("\nCreating a new enrollmentGroup...");
var certificate = new X509Certificate2(X509RootCertPath);
Attestation attestation = X509Attestation.CreateFromRootCertificates(certificate);
EnrollmentGroup enrollmentGroup =
new EnrollmentGroup(
EnrollmentGroupId,
attestation)
{
ProvisioningStatus = ProvisioningStatus.Enabled
};
Console.WriteLine(enrollmentGroup);
#endregion
#region Create the enrollmentGroup
Console.WriteLine("\nAdding new enrollmentGroup...");
EnrollmentGroup enrollmentGroupResult =
await provisioningServiceClient.CreateOrUpdateEnrollmentGroupAsync(enrollmentGroup).ConfigureAwait(false);
Console.WriteLine("\nEnrollmentGroup created with success.");
Console.WriteLine(enrollmentGroupResult);
#endregion
}
}
}
}
Well you are missing the SharedAccessKeyName
so the validation tries to check it and as it is null in your case you get the exception.
As you can see in the ServiceConnectionStringBuilder.cs the correct connection string format is
/// A valid connection string shall be in the following format:
/// <code>
/// HostName=[ServiceName];SharedAccessKeyName=[keyName];SharedAccessKey=[Key]
/// </code>
Also in line 128 you can see the check which throws your exception:
if (string.IsNullOrWhiteSpace(SharedAccessKeyName))
{
throw new ArgumentException("Should specify SharedAccessKeyName");
}
Now you might think that ServiceConnectionStringBuilder.cs is not used by your code, but the call ProvisioningServiceClient.CreateFromConnectionString
creates a new ProvisioningServiceClient instance, which in turn calls ServiceConnectionStringBuilder.Parse()
.
For more see ProvisioningServiceClient.cs in lines 82, 113 and 123.
SOLUTION:
To solve this you have to provide a SharedAccessKeyName. You should also consider using the IotHubConnectionStringBuilder for this which already checks your properties whhile building the connection string.
The questioner pointed out the key name is the deviceId according to this blog post here. Thus, the solution is to use SharedAccessKeyname=xx
instead of DeviceId=xx
.