Azure REST API插入实体时OData类型指定失败问题咨询
Azure Table Storage REST API 正确指定OData类型的方法
在使用REST API插入实体时,OData类型标记的格式必须严格匹配协议要求,格式错误会直接导致400 Bad Request。以下是两种常用请求格式的正确实现方式:
Atom XML格式
这是官方文档示例中常用的格式,核心注意点是命名空间声明和类型属性的正确使用:
- 请求头必须设置
Content-Type: application/atom+xml - 必须在
<entry>标签中声明三个命名空间:Atom、d(数据服务)、m(元数据服务) - 自定义字段的类型通过
m:type属性指定,属性值为官方定义的Edm类型(大小写敏感) - 字段内容必须与指定类型兼容(比如Edm.Guid必须是标准GUID字符串)
正确示例XML结构:
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"> <title /> <updated>2024-05-20T12:34:56Z</updated> <author><name /></author> <id /> <content type="application/xml"> <m:properties> <d:PartitionKey>TestPartition</d:PartitionKey> <d:RowKey>TestRow001</d:RowKey> <d:SessionID m:type="Edm.Guid">550e8400-e29b-41d4-a716-446655440000</d:SessionID> <d:TotalCount m:type="Edm.Int64">9876543210</d:TotalCount> <d:IsActive m:type="Edm.Boolean">true</d:IsActive> </m:properties> </content> </entry>
JSON格式
如果使用JSON提交请求,类型标记的格式与XML不同,需注意:
- 请求头设置为
Content-Type: application/json;odata=nometadata(最简格式,推荐) - 类型标记通过
[字段名]@odata.type的形式指定,与字段值同级 - Edm.Int64类型建议用字符串传递,避免数字精度丢失
正确示例JSON结构:
{ "PartitionKey": "TestPartition", "RowKey": "TestRow002", "SessionID": "550e8400-e29b-41d4-a716-446655440000", "SessionID@odata.type": "Edm.Guid", "TotalCount": "9876543210", "TotalCount@odata.type": "Edm.Int64", "IsActive": true, "IsActive@odata.type": "Edm.Boolean" }
通用注意事项
- Edm类型名称必须严格匹配:
Edm.String、Edm.Guid、Edm.Int64、Edm.Double、Edm.Boolean、Edm.DateTimeOffset等,大小写敏感 - 字段内容必须符合类型要求:比如
Edm.DateTimeOffset必须是ISO 8601格式(如2024-05-20T12:34:56Z) - 确保
PartitionKey和RowKey字段存在且格式正确,这两个是必填项 - 检查请求签名的正确性:虽然移除类型标记后请求成功,但如果签名有误也可能触发400,需确认签名逻辑正确
代码示例
PowerShell(JSON格式)
$storageAccount = "your-storage-account" $tableName = "your-table-name" $accountKey = "your-storage-key" $apiVersion = "2020-08-04" # 生成RFC1123格式的日期 $date = [DateTime]::UtcNow.ToString("R") $resourcePath = "/$storageAccount/$tableName" # 计算SharedKey签名(需自行实现或使用Azure模块的签名函数) $authHeader = "SharedKey $storageAccount : $(Get-StorageSharedKey -AccountName $storageAccount -AccountKey $accountKey -Resource $resourcePath -Date $date)" # 构建请求体 $requestBody = @" { "PartitionKey": "TestPartition", "RowKey": "PS-Test-001", "UserID": "1234567890123", "UserID@odata.type": "Edm.Int64", "SessionID": "550e8400-e29b-41d4-a716-446655440000", "SessionID@odata.type": "Edm.Guid" } "@ # 发送请求 $headers = @{ "x-ms-date" = $date "Authorization" = $authHeader "Content-Type" = "application/json;odata=nometadata" "x-ms-version" = $apiVersion } try { $response = Invoke-RestMethod -Uri "https://$storageAccount.table.core.windows.net/$tableName" -Method Post -Headers $headers -Body $requestBody Write-Host "实体插入成功:$($response.RowKey)" } catch { Write-Host "错误:$($_.Exception.Response.StatusCode) $($_.Exception.Response.StatusText)" Write-Host "响应内容:$($_.Exception.Response.Content.ReadAsStringAsync().Result)" }
VBScript(Atom XML格式)
Set xmlHttp = CreateObject("MSXML2.XMLHTTP.6.0") storageAccount = "your-storage-account" tableName = "your-table-name" accountKey = "your-storage-key" apiVersion = "2020-08-04" ' 生成RFC1123格式日期 dateStr = GetRFC1123Date() resourcePath = "/" & storageAccount & "/" & tableName authHeader = GetSharedKeyAuth(storageAccount, accountKey, resourcePath, dateStr) ' 构建请求URL和头部 requestUrl = "https://" & storageAccount & ".table.core.windows.net/" & tableName xmlHttp.Open "POST", requestUrl, False xmlHttp.setRequestHeader "x-ms-date", dateStr xmlHttp.setRequestHeader "Authorization", authHeader xmlHttp.setRequestHeader "Content-Type", "application/atom+xml" xmlHttp.setRequestHeader "x-ms-version", apiVersion ' 构建XML请求体 xmlBody = "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:d='http://schemas.microsoft.com/ado/2007/08/dataservices' xmlns:m='http://schemas.microsoft.com/ado/2007/08/dataservices/metadata'>" & _ "<title />" & _ "<updated>" & GetISODate() & "</updated>" & _ "<author><name /></author>" & _ "<id />" & _ "<content type='application/xml'>" & _ "<m:properties>" & _ "<d:PartitionKey>TestPartition</d:PartitionKey>" & _ "<d:RowKey>VBS-Test-001</d:RowKey>" & _ "<d:UserID m:type='Edm.Int64'>1234567890123</d:UserID>" & _ "<d:SessionID m:type='Edm.Guid'>550e8400-e29b-41d4-a716-446655440000</d:SessionID>" & _ "</m:properties>" & _ "</content>" & _ "</entry>" ' 发送请求 xmlHttp.send xmlBody If xmlHttp.Status = 201 Then WScript.Echo "实体插入成功" Else WScript.Echo "错误代码:" & xmlHttp.Status & " " & xmlHttp.statusText WScript.Echo "响应详情:" & xmlHttp.responseText End If ' 辅助函数:生成RFC1123格式日期 Function GetRFC1123Date() Dim dt, tz dt = UTCNow() tz = "GMT" GetRFC1123Date = WeekdayName(Weekday(dt), False) & ", " & _ Right("0" & Day(dt), 2) & " " & _ MonthName(Month(dt), True) & " " & _ Year(dt) & " " & _ Right("0" & Hour(dt), 2) & ":" & _ Right("0" & Minute(dt), 2) & ":" & _ Right("0" & Second(dt), 2) & " " & tz End Function ' 辅助函数:生成ISO格式日期 Function GetISODate() Dim dt dt = UTCNow() GetISODate = Year(dt) & "-" & Right("0" & Month(dt), 2) & "-" & Right("0" & Day(dt), 2) & "T" & _ Right("0" & Hour(dt), 2) & ":" & Right("0" & Minute(dt), 2) & ":" & Right("0" & Second(dt), 2) & "Z" End Function ' 辅助函数:获取UTC时间 Function UTCNow() UTCNow = DateAdd("h", -DateDiff("h", Now(), UTCNow()), Now()) End Function ' 辅助函数:计算SharedKey签名(需自行实现完整的HMAC-SHA256签名逻辑) Function GetSharedKeyAuth(accountName, accountKey, resource, dateStr) ' 实现签名逻辑,生成符合要求的Authorization头部 GetSharedKeyAuth = "SharedKey " & accountName & ": [签名内容]" End Function
内容的提问来源于stack exchange,提问作者Tim
相关产品推荐
相关产品推荐

