Azure表存储返回400 Bad Request

时间:2013-02-13 17:30:15

标签: c# azure exception azure-table-storage

我在调试模式下运行它,并附上一个包含异常细节的图像。我怎么知道出了什么问题?我试图在表格中插入数据。天蓝不能给我更多细节吗?

Obs:存储在Windows Azure上,而不在我的计算机上。表已创建,但插入数据时出现此错误

enter image description here

// Retrieve the storage account from the connection string.
Microsoft.WindowsAzure.Storage.CloudStorageAccount storageAccount = Microsoft.WindowsAzure.Storage.CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=***;AccountKey=***");

// Create the table client.
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

// Create the table if it doesn't exist.
CloudTable table = tableClient.GetTableReference("EmployeeOnlineHistory");
table.CreateIfNotExists();

,这是插入代码:

public static void SetStatus(Employee e, bool value)
{
    try
    {
        // Retrieve the storage account from the connection string.
        Microsoft.WindowsAzure.Storage.CloudStorageAccount storageAccount = Microsoft.WindowsAzure.Storage.CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=###;AccountKey=###");

        // Create the table client.
        CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

        // Create the CloudTable object that represents the "people" table.
        CloudTable table = tableClient.GetTableReference("EmployeeOnlineHistory");

        // Create a new customer entity.

        if (value == true)
        {
            EmployeeOnlineHistory empHistory = new EmployeeOnlineHistory(e.Id);
            empHistory.IsOnline = true;
            empHistory.OnlineTimestamp = DateTime.Now;
            TableOperation insertOperation = TableOperation.Insert(empHistory);
            table.Execute(insertOperation);
        }
        else
        {
            TableQuery<EmployeeOnlineHistory> query = new TableQuery<EmployeeOnlineHistory>()
                .Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, e.Id.ToString()));
            EmployeeOnlineHistory entity = table.ExecuteQuery(query).Take(1).FirstOrDefault();

            if ((entity!=null)&&(entity.IsOnline))
            {
                entity.IsOnline = false;
                entity.OfflineTimestamp = DateTime.Now;
                entity.OnlineTime = (entity.OfflineTimestamp - entity.OnlineTimestamp);
                TableOperation updateOperation = TableOperation.Replace(entity);
                table.Execute(updateOperation);
            }
            else
            {
                EmployeeOnlineHistory empHistory = new EmployeeOnlineHistory(e.Id);
                empHistory.IsOnline = false;
                empHistory.OfflineTimestamp = DateTime.Now;
                TableOperation insertOperation = TableOperation.Insert(empHistory);
                table.Execute(insertOperation);
            }
        }
    }
    catch (Exception ex)
    {
        //var details = new System.IO.StreamReader(((Microsoft.WindowsAzure.Storage.StorageException)ex)..Response.GetResponseStream()).ReadToEnd();
        LogFile.Error("EmployeeOnlineHistory.setStatus",ex);
    }
}

22 个答案:

答案 0 :(得分:129)

400错误表示您的某个属性的值存在问题。找到答案的一种方法是通过Fiddler跟踪请求/响应,并查看发送到Windows Azure存储的实际数据。

猜测一下,我假设快速浏览一下您的模型中的代码,您有一些日期/时间类型属性(OfflineTimestamp,OnlineTimestamp),并观察到在某些情况下,其中一个初始化为默认值为“ DateTime.MinValue ”。请注意,Windows Azure [http://msdn.microsoft.com/en-us/library/windowsazure/dd179338.aspx]中日期/时间类型属性允许的最小值为1月1日,1601(UTC)。请查看是否不是这样。如果是这种情况,那么您可以将它们设置为可空类型字段,以便它们不会填充默认值。

请看下面的JuhaPalomäki的答案......在他建议的例外情况中,有时候会有一些更有用的消息(RequestInformation.ExtendedErrorInformation.ErrorMessage)

答案 1 :(得分:107)

StorageException还包含有关错误的更详细信息。

签入调试器:StorageException.RequestInformation.ExtendedInformation

enter image description here

答案 2 :(得分:45)

在我的情况下,它是 RowKey 中的正斜杠。

我还收到了'OutOfRangeInput - 其中一个请求输入超出了范围。'尝试通过存储模拟器手动添加时出错。

  

关键字段中不允许使用的字符

     

以下字符不允许使用以下字符    PartitionKey RowKey 属性:

     
      
  • 正斜杠( / )字符
  •   
  • 反斜杠( \ )字符
  •   
  • 数字符号()字符
  •   
  • 问号()字符
  •   
  • 控制 U + 0000至U + 001F 中的字符,包括:      
        
    • 水平制表符( \ t )字符
    •   
    • 换行符( \ n
    •   
    • 回车符( \ r )字符
    •   
    • 控制字符从 U + 007F到U + 009F
    •   
  •   

http://msdn.microsoft.com/en-us/library/dd179338.aspx

我写了一个扩展方法来为我处理这个问题。

public static string ToAzureKeyString(this string str)
{
    var sb = new StringBuilder();
    foreach (var c in str
        .Where(c => c != '/'
                    && c != '\\'
                    && c != '#'
                    && c != '/'
                    && c != '?'
                    && !char.IsControl(c)))
        sb.Append(c);
    return sb.ToString();
}

答案 3 :(得分:5)

好吧,在我的情况下,我试图这样做:

CloudBlobContainer container = blobClient.GetContainerReference("SessionMaterials");
await container.CreateIfNotExistsAsync();

因为ContainerName SessionMaterials(作为Pascal Case和Camel Case中的习惯写作:D)它导致400个错误请求。所以, 我只需要做sessionmaterials。 它起作用了。

希望这对某人有所帮助。

PS: - 只需检查异常http响应或使用fiddler捕获请求和响应。

答案 4 :(得分:4)

我遇到了同样的问题,但我的理由是因为尺寸问题。在深入了解其他异常属性(RequestInformation.ExtendedErrorInformation)后,找到了原因:

ErrorCode:PropertyValueTooLarge ErrorMessage:属性值超过允许的最大大小(64KB)。如果属性值是字符串,则为UTF-16编码,最大字符数应为32K或更少。

答案 5 :(得分:3)

有时因为partitionKeyrowKeyNULL

(我的情况就是如此)

答案 6 :(得分:3)

在我的情况下:  容器名称是大写字母。使用字符时有局限性。 enter image description here

答案 7 :(得分:1)

可以找到MS关于所有表格服务错误代码的文档here

答案 8 :(得分:1)

我有相同的BadRequest(400)错误,最后我手动填写:

enter image description here

为我工作。希望这有帮助!

答案 9 :(得分:0)

对我来说,我尝试使用包含“#”字符的 PartitionKey/RowKey 将一个实体插入到 Azure 存储表中。令人讨厌的是,这是不允许的,因为在单表设计中使用“#”作为分隔符是很常见的。

答案 10 :(得分:0)

对我来说,我使用了带破折号的表名示例:tablename: "table-1234",但没有破折号的 tablename: "table1234" 有效。

答案 11 :(得分:0)

当我尝试将太长的值放入字符串字段时,我收到了 400-BadRequest 响应。

“UTF-16 编码的值。字符串值的大小可能高达 64 KiB。请注意,支持的最大字符数约为 32 K 或更少。”

https://docs.microsoft.com/en-us/rest/api/storageservices/understanding-the-table-service-data-model

答案 12 :(得分:0)

我遇到了同样的问题,该函数将containerNameKey作为字符串传递。下面是给出错误的代码

container = blobClient.GetContainerReference(containerNameKey) 

我将其更改为

container = blobClient.GetContainerReference(ConfigurationManager.AppSettings(containerNameKey).ToString()) 

有效

答案 13 :(得分:0)

在创建“ TableBotDataStore”类(MS bot框架)的新设备的情况下,我们将带有连字符的“ tableName”参数传递给“ master-bot”,并且TableBotDataStore的表名称只能包含字母和数字

答案 14 :(得分:0)

我从Azure存储帐户表API得到了400-BadRequest响应。异常信息显示“正在访问的帐户不支持http。”。我认为在存储帐户配置中启用了“需要安全传输”后,必须在连接字符串中使用https,如下图所示。enter image description here

答案 15 :(得分:0)

如果您使用的是NodeJS,却偶然发现了这篇文章,结果发现您在错误对象中没有得到这么可爱的详细信息;您可以利用代理获取这些详细信息。但是,由于这里没有人提到如何使用代理。

使用NodeJS的最简单方法是设置两个环境变量:

html is:<a href="http.someurl.com" class="tango">abc news</a>

如果您实际上是在使用C#,就像这篇文章的作者所做的那样;您只需安装Fiddler并将其设置为拦截即可。默认情况下,它应拦截请求。您可能还需要信任Fiddler的证书或以其他方式执行Node的“ NODE_TLS_REJECT_UNAUTHORIZED = 0”。

答案 16 :(得分:0)

就我而言,我不应在我的实体类中添加PartitionKey和Rowkey。它应该来自基类。下面就可以了。

public class TableRunLogMessage:TableEntity
{
      public string status { get; set; }
      public long logged { get; set; }


      public TableRunLogMessage() { }
}

答案 17 :(得分:0)

在我的情况下:我在blob元数据中添加了带有连字符的标记名称。

<!DOCTYPE html>
<html>
  <head>
    <title></title>
  </head>
  <body style="width: 750px; height: 400px">
    <div class="tradingview-widget-container">
      <div id="tradingview_e4c1e"></div>
      <div class="tradingview-widget-copyright"><a href="https://www.tradingview.com/symbols/BINANCE-XLMUSD/" 
        rel="noopener" target="_blank"><span class="blue-text">XLMUSD chart</span></a> by TradingView</div>
      <script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>
      <script type="text/javascript">
      new TradingView.widget(
      {
        "width": 750,
        "height": 400,
        "symbol": "BINANCE:XLMUSD",
        "interval": "D",
        "timezone": "Etc/UTC",
        "theme": "Dark",
        "style": "1",
        "locale": "en",
        "toolbar_bg": "rgba(0, 0, 0, 1)",
        "enable_publishing": false,
        "container_id": "tradingview_e4c1e"
    });
      </script>
    </div>
  </body>
</html>

var blob = container.GetBlockBlobReference(filename); blob.Metadata.Add("added-by", Environment.UserName); //.. other metadata blob.UploadFromStream(filestream); 中的破折号是问题所在,后来RTFM告诉我标记名称必须符合C#标识符约定。

参考:https://docs.microsoft.com/en-us/azure/storage/blobs/storage-properties-metadata

下划线工作正常。

答案 18 :(得分:0)

我也面临同样的问题。在我的情况下,未设置PartitionKey值,因此默认情况下PartitionKey值为null,这导致 update C set C.ORIG = C.ICD10 --SELECT C.ORIG,C.ICD9,C.ICD10 from ( select xr.ORIG, xr.ICD9, xr.ICD10 FROM ( select ORIG, ICD9, ICD10 ,ROW_NUMBER() OVER (PARTITION BY ICD9 ORDER BY ICD9) Rn FROM extract_icd10_9_xref x join extract_icd10_9_xref y on x.ORIG = y.ICD9 ) XR where XR.Rn = 1 )C 异常

检查您是否为PartitionKey或RowKey提供了适当的值,您可能会遇到此类问题。

答案 19 :(得分:0)

我收到了一个(400)Bad Request,StatusMessage:Bad Request,ErrorCode:OutOfRangeInput,当实体有一个属性DateTime未设置(= DateTime.MinValue)

答案 20 :(得分:0)

我收到400 Bad Request,因为我使用的是ZRS(Zone Redundant Storage),而且这种类型的存储无法使用Analytics。我不知道我在使用Google Analytics。

我删除了存储容器并重新创建为GRS,现在工作正常。

答案 21 :(得分:0)

我修复了我的案例并且工作正常

我的案例:

  1. 行键格式不正确(400)。
  2. partitionkey和rowkey的组合不是唯一的(409)。