Azure表存储返回400 Bad Request

问题描述 投票:105回答:17

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

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();

这是插入代码:

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);
    }
}
c# azure exception azure-table-storage
17个回答
132
投票

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)


0
投票

我也遇到过同样的问题。在我的情况下,PartitionKey值未设置,因此默认情况下PartitionKey值为null,这导致Object reference not set to an instance of an object.异常

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


0
投票

我修好了我的案子并且工作正常

我的案子:

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

0
投票

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

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


0
投票

当实体具有未设置的属性DateTime(= DateTime.MinValue)时,我得到(400)Bad Request,StatusMessage:Bad Request,ErrorCode:OutOfRangeInput


0
投票

在我的例子中:我包含了包含连字符的标签名称的blob元数据。

var blob = container.GetBlockBlobReference(filename);
blob.Metadata.Add("added-by", Environment.UserName);
//.. other metadata
blob.UploadFromStream(filestream);

"added-by"中的破折号是问题,后来RTFM告诉我标签名称必须符合C#标识符约定。

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

下划线工作正常。


0
投票

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

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


      public TableRunLogMessage() { }
}

0
投票

如果您正在使用NodeJS并偶然发现这篇文章,那么只是发现您没有在错误对象中获得那些可爱的详细信息;您可以使用代理来获取这些详细信息。但是,因为这里没有人提到如何使用代理。

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

NODE_TLS_REJECT_UNAUTHORIZED=0
This disables SSL checks so you can intercept your own SSL requests. This leaves you open to Man-in-The-Middle attacks and should NEVER make it to production, and I wouldn't even leave it in development for long. However, it will allow you to intercept the HTTP Requests.

HTTP_PROXY=http://127.0.0.1:8888
This sets node to utilize a proxy listening on your localhost at port 8888. Port 8888 is the default for Fiddler. Many other proxies default to 8080.

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


0
投票

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


0
投票

在我创建“TableBotDataStore”类(MS bot框架)的新安装的情况下,我们传递带有连字符的“tableName”参数,如“master-bot”,TableBotDataStore只能使用字母和数字的表名


112
投票

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

签入调试器:StorageException.RequestInformation.ExtendedInformation


46
投票

在我的例子中,它是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();
}

5
投票

好吧,就我而言,我试图这样做:

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

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

希望这对某人有所帮助。

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


4
投票

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

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


3
投票

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


3
投票

有时这是因为你的partitionKeyrowKeyNULL

(我的情况就是这样)


1
投票

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


1
投票

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

enter image description here

并为我工作。希望这可以帮助!

© www.soinside.com 2019 - 2024. All rights reserved.