C# 从ARM模板部署新Azure VM时,无法格式化.WithParameters()的有效JObject
目前,我在使用C#编写的Azure函数从ARM模板部署Azure VM时遇到问题,同时使用Newjonsoft.Json、Linq库中的JObject为新VM提供参数 JObject.FromObject()方法以C# 从ARM模板部署新Azure VM时,无法格式化.WithParameters()的有效JObject,c#,json,azure,json.net,arm-template,C#,Json,Azure,Json.net,Arm Template,目前,我在使用C#编写的Azure函数从ARM模板部署Azure VM时遇到问题,同时使用Newjonsoft.Json、Linq库中的JObject为新VM提供参数 JObject.FromObject()方法以“{”paramName:“paramValue”}”的格式制定参数,但是我认为它需要制定为“{”paramName:{”value:“paramValue”}。我不确定是否还需要指定“contentVersion”和“$schema”ARM模板参数才能工作 到目前为止,我尝试使用动态
“{”paramName:“paramValue”}”
的格式制定参数,但是我认为它需要制定为“{”paramName:{”value:“paramValue”}
。我不确定是否还需要指定“contentVersion”和“$schema”ARM模板参数才能工作
到目前为止,我尝试使用动态变量来表示对象,然后将其转换为字符串并使用JObject.Parse()方法进行解析,但是这只能产生与前面所述相同的结果
Azure函数代码示例(并非所有代码):
ARM模板部署类代码示例(并非所有代码):
作为预期的结果,我希望代码能够简单地启动到Azure资源组的ARM模板部署,但是当前它失败了,并显示以下消息:
'请求内容无效,无法反序列化:'错误
将值“parameterValue”转换为类型
“Microsoft.WindowsAzure.ResourceStack.Frontdoor.Data.Definitions.DeploymentParameterDefinition”。
路径“properties.parameters.vNetResourceGroup”,第8行,位置
48.“
根据我的测试,如果你想用一个动态变量来描述这个对象,我们需要创建一个新的JObject mytemplate.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"adminUsername": { "type": "string" },
"adminPassword": { "type": "securestring" }
},
"variables": {
"vnetID": "[resourceId('Microsoft.Network/virtualNetworks','myVNet123456')]",
"subnetRef": "[concat(variables('vnetID'),'/subnets/mySubnet')]"
},
"resources": [
{
"apiVersion": "2016-03-30",
"type": "Microsoft.Network/publicIPAddresses",
"name": "myPublicIPAddress123456",
"location": "[resourceGroup().location]",
"properties": {
"publicIPAllocationMethod": "Dynamic",
"dnsSettings": {
"domainNameLabel": "myresourcegroupdns15896"
}
}
},
{
"apiVersion": "2016-03-30",
"type": "Microsoft.Network/virtualNetworks",
"name": "myVNet123456",
"location": "[resourceGroup().location]",
"properties": {
"addressSpace": { "addressPrefixes": [ "10.0.0.0/16" ] },
"subnets": [
{
"name": "mySubnet",
"properties": { "addressPrefix": "10.0.0.0/24" }
}
]
}
},
{
"apiVersion": "2016-03-30",
"type": "Microsoft.Network/networkInterfaces",
"name": "myNic562354",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Network/publicIPAddresses/', 'myPublicIPAddress123456')]",
"[resourceId('Microsoft.Network/virtualNetworks/', 'myVNet')]"
],
"properties": {
"ipConfigurations": [
{
"name": "ipconfig1",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"publicIPAddress": { "id": "[resourceId('Microsoft.Network/publicIPAddresses','myPublicIPAddress123456')]" },
"subnet": { "id": "[variables('subnetRef')]" }
}
}
]
}
},
{
"apiVersion": "2016-04-30-preview",
"type": "Microsoft.Compute/virtualMachines",
"name": "myVM",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Network/networkInterfaces/', 'myNic562354')]"
],
"properties": {
"hardwareProfile": { "vmSize": "Standard_DS1" },
"osProfile": {
"computerName": "myVM",
"adminUsername": "[parameters('adminUsername')]",
"adminPassword": "[parameters('adminPassword')]"
},
"storageProfile": {
"imageReference": {
"publisher": "MicrosoftWindowsServer",
"offer": "WindowsServer",
"sku": "2012-R2-Datacenter",
"version": "latest"
},
"osDisk": {
"name": "myManagedOSDisk",
"caching": "ReadWrite",
"createOption": "FromImage"
}
},
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces','myNic562354')]"
}
]
}
}
}
]
}
我的代码
JObject parametesObjectv1 = new JObject(
new JProperty("adminUsername",
new JObject(
new JProperty("value", "azureuser")
)
),
new JProperty("adminPassword",
new JObject(
new JProperty("value", "Azure12345678")
)
)
);
var credentials = SdkContext.AzureCredentialsFactory.FromServicePrincipal(clientId, clientSecret, tenantId, AzureEnvironment.AzureGlobalCloud);
var azure = Azure
.Configure()
.WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
.Authenticate(credentials)
.WithSubscription(subscriptionId);
if (azure.ResourceGroups.Contain(resourceGroupName) == false)
{
var resourceGroup = azure.ResourceGroups.Define(resourceGroupName)
.WithRegion(resourceGroupLocation)
.Create();
}
Console.WriteLine("start");
var deployment = azure.Deployments.Define(deploymentName)
.WithExistingResourceGroup(resourceGroupName)
.WithTemplateLink(pathToTemplateFile, "1.0.0.0")
.WithParameters(parametesObjectv1)
.WithMode(Microsoft.Azure.Management.ResourceManager.Fluent.Models.DeploymentMode.Incremental)
.Create();
另外,如果不想使用动态变量,可以直接提供parameter.json和template.json的url来创建资源
var deployment = azure.Deployments.Define(deploymentName)
.WithExistingResourceGroup(resourceGroupName)
.WithTemplateLink(pathToTemplateFile, "1.0.0.0")
.WithParametersLink(pathToJsonFile, "1.0.0.0")
.WithMode(Microsoft.Azure.Management.ResourceManager.Fluent.Models.DeploymentMode.Incremental)
.Create();
根据我的测试,如果你想用一个动态变量来描述这个对象,我们需要创建一个新的JObject mytemplate.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"adminUsername": { "type": "string" },
"adminPassword": { "type": "securestring" }
},
"variables": {
"vnetID": "[resourceId('Microsoft.Network/virtualNetworks','myVNet123456')]",
"subnetRef": "[concat(variables('vnetID'),'/subnets/mySubnet')]"
},
"resources": [
{
"apiVersion": "2016-03-30",
"type": "Microsoft.Network/publicIPAddresses",
"name": "myPublicIPAddress123456",
"location": "[resourceGroup().location]",
"properties": {
"publicIPAllocationMethod": "Dynamic",
"dnsSettings": {
"domainNameLabel": "myresourcegroupdns15896"
}
}
},
{
"apiVersion": "2016-03-30",
"type": "Microsoft.Network/virtualNetworks",
"name": "myVNet123456",
"location": "[resourceGroup().location]",
"properties": {
"addressSpace": { "addressPrefixes": [ "10.0.0.0/16" ] },
"subnets": [
{
"name": "mySubnet",
"properties": { "addressPrefix": "10.0.0.0/24" }
}
]
}
},
{
"apiVersion": "2016-03-30",
"type": "Microsoft.Network/networkInterfaces",
"name": "myNic562354",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Network/publicIPAddresses/', 'myPublicIPAddress123456')]",
"[resourceId('Microsoft.Network/virtualNetworks/', 'myVNet')]"
],
"properties": {
"ipConfigurations": [
{
"name": "ipconfig1",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"publicIPAddress": { "id": "[resourceId('Microsoft.Network/publicIPAddresses','myPublicIPAddress123456')]" },
"subnet": { "id": "[variables('subnetRef')]" }
}
}
]
}
},
{
"apiVersion": "2016-04-30-preview",
"type": "Microsoft.Compute/virtualMachines",
"name": "myVM",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Network/networkInterfaces/', 'myNic562354')]"
],
"properties": {
"hardwareProfile": { "vmSize": "Standard_DS1" },
"osProfile": {
"computerName": "myVM",
"adminUsername": "[parameters('adminUsername')]",
"adminPassword": "[parameters('adminPassword')]"
},
"storageProfile": {
"imageReference": {
"publisher": "MicrosoftWindowsServer",
"offer": "WindowsServer",
"sku": "2012-R2-Datacenter",
"version": "latest"
},
"osDisk": {
"name": "myManagedOSDisk",
"caching": "ReadWrite",
"createOption": "FromImage"
}
},
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces','myNic562354')]"
}
]
}
}
}
]
}
我的代码
JObject parametesObjectv1 = new JObject(
new JProperty("adminUsername",
new JObject(
new JProperty("value", "azureuser")
)
),
new JProperty("adminPassword",
new JObject(
new JProperty("value", "Azure12345678")
)
)
);
var credentials = SdkContext.AzureCredentialsFactory.FromServicePrincipal(clientId, clientSecret, tenantId, AzureEnvironment.AzureGlobalCloud);
var azure = Azure
.Configure()
.WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
.Authenticate(credentials)
.WithSubscription(subscriptionId);
if (azure.ResourceGroups.Contain(resourceGroupName) == false)
{
var resourceGroup = azure.ResourceGroups.Define(resourceGroupName)
.WithRegion(resourceGroupLocation)
.Create();
}
Console.WriteLine("start");
var deployment = azure.Deployments.Define(deploymentName)
.WithExistingResourceGroup(resourceGroupName)
.WithTemplateLink(pathToTemplateFile, "1.0.0.0")
.WithParameters(parametesObjectv1)
.WithMode(Microsoft.Azure.Management.ResourceManager.Fluent.Models.DeploymentMode.Incremental)
.Create();
另外,如果不想使用动态变量,可以直接提供parameter.json和template.json的url来创建资源
var deployment = azure.Deployments.Define(deploymentName)
.WithExistingResourceGroup(resourceGroupName)
.WithTemplateLink(pathToTemplateFile, "1.0.0.0")
.WithParametersLink(pathToJsonFile, "1.0.0.0")
.WithMode(Microsoft.Azure.Management.ResourceManager.Fluent.Models.DeploymentMode.Incremental)
.Create();
我能够通过构造基于参数类型的类来解决这个问题,并制定了一种方法来将参数值映射到ARM参数类型 ARM模板参数类提取:
namespace FuncApp.MSAzure.ARMTemplates.ARMParaneterTypes
{
public class ParameterValueString
{
public string Value { get; set; }
}
public class ParameterValueArray
{
public string[] Value { get; set; }
}
public class ParameterBoolValue
{
public bool Value { get; set; }
}
}
namespace FuncApp.MSAzure.VirtualMachines
{
public class AzNewVmRequestArmParameters
{
public ParameterValueString location { get; set; }
public ParameterValueString adminUsername { get; set; }
public ParameterValueString adminPassword { get; set; }
}
}
映射类方法提取:
public static AzNewVmRequestArmParameters ToArmParameters(
this AzNewVmRequest requestContent,
string adminUsername,
string adminPassword
)
{
return new AzNewVmRequestArmParameters
{
location = new ParameterValueString {
Value = requestContent.Location
},
adminUsername = new ParameterValueString
{
Value = adminUsername
},
adminPassword = new ParameterValueString
{
Value = adminPassword
},
};
}
“AzNewVmRequestArmParameters”模型类提取:
namespace FuncApp.MSAzure.ARMTemplates.ARMParaneterTypes
{
public class ParameterValueString
{
public string Value { get; set; }
}
public class ParameterValueArray
{
public string[] Value { get; set; }
}
public class ParameterBoolValue
{
public bool Value { get; set; }
}
}
namespace FuncApp.MSAzure.VirtualMachines
{
public class AzNewVmRequestArmParameters
{
public ParameterValueString location { get; set; }
public ParameterValueString adminUsername { get; set; }
public ParameterValueString adminPassword { get; set; }
}
}
有了这些,我可以运行下面的代码(简化),用API可以准备好的参数制定一个有效的jObject变量:
var parameters = azureVmDeploymentRequest.ToArmParameters(
adminUsername: "azurevmadmin",
adminPassword: "P@ssword123!"
);
var jParameters = JObject.FromObject(parameters);
我能够通过构造基于参数类型的类来解决这个问题,并制定了一种方法来将参数值映射到ARM参数类型 ARM模板参数类提取:
namespace FuncApp.MSAzure.ARMTemplates.ARMParaneterTypes
{
public class ParameterValueString
{
public string Value { get; set; }
}
public class ParameterValueArray
{
public string[] Value { get; set; }
}
public class ParameterBoolValue
{
public bool Value { get; set; }
}
}
namespace FuncApp.MSAzure.VirtualMachines
{
public class AzNewVmRequestArmParameters
{
public ParameterValueString location { get; set; }
public ParameterValueString adminUsername { get; set; }
public ParameterValueString adminPassword { get; set; }
}
}
映射类方法提取:
public static AzNewVmRequestArmParameters ToArmParameters(
this AzNewVmRequest requestContent,
string adminUsername,
string adminPassword
)
{
return new AzNewVmRequestArmParameters
{
location = new ParameterValueString {
Value = requestContent.Location
},
adminUsername = new ParameterValueString
{
Value = adminUsername
},
adminPassword = new ParameterValueString
{
Value = adminPassword
},
};
}
“AzNewVmRequestArmParameters”模型类提取:
namespace FuncApp.MSAzure.ARMTemplates.ARMParaneterTypes
{
public class ParameterValueString
{
public string Value { get; set; }
}
public class ParameterValueArray
{
public string[] Value { get; set; }
}
public class ParameterBoolValue
{
public bool Value { get; set; }
}
}
namespace FuncApp.MSAzure.VirtualMachines
{
public class AzNewVmRequestArmParameters
{
public ParameterValueString location { get; set; }
public ParameterValueString adminUsername { get; set; }
public ParameterValueString adminPassword { get; set; }
}
}
有了这些,我可以运行下面的代码(简化),用API可以准备好的参数制定一个有效的jObject变量:
var parameters = azureVmDeploymentRequest.ToArmParameters(
adminUsername: "azurevmadmin",
adminPassword: "P@ssword123!"
);
var jParameters = JObject.FromObject(parameters);
你能给出一个git repo的示例吗?然后我可以看一看你能发布参数的预期JSON吗?以及你在这里得到的那个吗?你能给出一个git repo的示例吗?然后我可以看一看你能发布参数的预期JSON吗?以及你在这里得到的JSON吗?嗨,Jim,谢谢你出色、详细的回复。我会试试这个出来,让你知道它是否对我有效。:!嗨,你的方法很好,但是我也能够通过构造基于参数类型的类,用一种稍微长一点的方法来解决它,并制定了一个方法来将参数值映射到ARM参数类型。嗨,Jim,谢谢你的出色、详细的回答。我将尝试这个方法出来,让你知道它是否对我有效。:!您好,您的方法工作得很好,但是我也能够通过构造基于参数类型的类以稍微冗长的方式解决它,并制定了一个方法来将参数值映射到ARM参数类型。