Azure表存储返回400 Bad Request

Rya*_*yan 111 c# exception azure azure-table-storage

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

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

在此输入图像描述

// 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();
Run Code Online (Sandbox Code Playgroud)

这是插入代码:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Gau*_*tri 133

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

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

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

  • 对于上帝的爱,如果Azure团队中有人读到这个,请让SDK返回比400 Bad Request错误更多的信息.我不知道为什么表存储中的DateTime不能与.NET DateTime对象具有相同的最小日期,但是我在这个上浪费了一个美好的一天.当我找到导致问题的财产时,我发生了这个问题,这有助于.现在,在我使用DateTime为表存储插入/更新模型之前,我必须对所有DateTime属性运行检查.不理想...... (238认同)
  • 显然,表名也不能有连字符.花了我一个小时来弄明白. (12认同)
  • 虽然我们在这里,但你也不能拥有枚举属性.我不得不将属性转换为Integer (8认同)
  • 表名也不能带有下划线..这就是为什么我在这里 (2认同)
  • 我想RowKey没有用空字符串初始化,因为这是主要的查找值而且只有索引列...这是为了提醒你填充它我会想到....这只是我猜的...尽管...表名去..阅读本文... https://blogs.msdn.microsoft.com/jmstall/2014/06/12/azure-storage-naming-rules/ (2认同)

Juh*_*äki 116

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

签入调试器:StorageException.RequestInformation.ExtendedInformation

在此输入图像描述

  • 为什么这些信息不是顶级例外? (5认同)

Sha*_*awn 49

在我的例子中,它是RowKey中的正斜杠.

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

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

PartitionKeyRowKey属性的值中不允许使用以下字符 :

  • 正斜杠(/)字符
  • 反斜杠(\)字符
  • 数字符号(#)字符
  • 问号()字符
  • 控制字符从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();
}
Run Code Online (Sandbox Code Playgroud)

  • 这也是我的问题.你的扩展方法就像一个冠军! (4认同)

小智 5

我遇到了同样的问题,但我的情况是由于尺寸而引起的。在深入研究其他异常属性(RequestInformation.ExtendedErrorInformation)之后,找到了原因:

错误代码:PropertyValueTooLarge错误消息:属性值超出了允许的最大大小(64KB)。如果属性值为字符串,则它是UTF-16编码的,最大字符数应为32K或更少。


Jaw*_*ngh 5

好吧,就我而言,我正在尝试这样做:

CloudBlobContainer container = blobClient.GetContainerReference("SessionMaterials");
await container.CreateIfNotExistsAsync();
Run Code Online (Sandbox Code Playgroud)

由于ContainerName SessionMaterials(作为习惯在Pascal Case和Camel Case:D中编写),它导致了400个错误的请求。所以,我只需要做到sessionmaterials。而且有效。

希望这可以帮助一些人。

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