Лазурное хранилище таблиц возвращает 400 Bad Request

Я запускал это в режиме отладки, и я прикрепляю изображение с подробностями исключения. Как я могу узнать, что пошло не так? Я пытался вставить данные в таблицу. Не могу получить более подробную информацию?

Наблюдение: хранилище находится на 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);
    }
}

Ответ 1

400 Ошибка означает, что что-то не так со значением одного из ваших свойств. Один из способов узнать - проследить запрос/ответ через Fiddler и посмотреть фактические данные, отправляемые в Windows Azure Storage.

Принимая дикие предположения, я предполагаю, быстро взглянув на ваш код, что в вашей модели у вас есть свойства типа Date/Time (OfflineTimestamp, OnlineTimestamp), и заметил, что в определенных сценариях один из них инициализируется значение по умолчанию, которое " DateTime.MinValue". Обратите внимание, что минимальное значение, разрешенное для атрибута типа Date/Time, составляет 1 января 1601 (UTC) в Windows Azure [ http://msdn.microsoft.com/en-us/library/windowsazure/dd179338.aspx]. Пожалуйста, посмотрите, не так ли. Если это так, то вы можете сделать их полями с нулевым типом, чтобы они не заполнялись значениями по умолчанию.

Посмотрите на Juha Palomäki ответ ниже, а также... там иногда есть несколько более полезное сообщение в исключении, где он предлагает (RequestInformation.ExtendedErrorInformation.ErrorMessage)

Ответ 2

В StorageException содержится также немного более подробная информация об ошибке.

Проверка отладки: StorageException.RequestInformation.ExtendedInformation

enter image description here

Ответ 3

В моем случае это была косая черта в RowKey.

Я также получил "OutOfRangeInput" - один из входных данных запроса выходит за пределы диапазона. при попытке добавить вручную через эмулятор хранилища.

Символы, запрещенные в ключевых полях

Следующие символы недопустимы для значений для PartitionKey и RowKey:

  • Символ прямой косой черты (/)
  • Символ обратной косой черты (\)
  • Символ номера ( #)
  • Символ вопросительного знака (?)
  • Управляющие символы от U + 0000 до U + 001F, включая:
    • Символ горизонтальной вкладки (\t)
    • Символ linefeed (\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();
}

Ответ 4

ну, в моем случае я пытался сделать это:

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

из-за ContainerName SessionMaterials (как привычка писать в Pascal Case и Camel Case: D) он вызывал 400 неправильных запросов. Итак, я просто должен сделать это sessionmaterials. и это сработало.

Надеюсь, это кому-нибудь поможет.

PS: - Просто проверьте исключение http ответа или используйте fiddler для захвата запроса и ответа.

Ответ 5

Я столкнулся с той же проблемой, но причина в моем случае была связана с размером. После поиска дополнительных свойств исключений (RequestInformation.ExtendedErrorInformation) выяснилось, что:

ErrorCode: PropertyValueTooLarge ErrorMessage: значение свойства превышает максимально допустимый размер (64 КБ). Если значением свойства является строка, то кодируется UTF-16, а максимальное количество символов должно быть 32 КБ или меньше.

Ответ 6

Иногда это потому, что ваш partitionKey или rowKey равен NULL

(это был случай для меня)

Ответ 7

в моем случае:  Название контейнера было написано заглавными буквами. существуют ограничения при использовании символов. введите описание изображения здесь

Ответ 8

Документацию от MS о всех кодах ошибок службы таблицы можно найти здесь

Ответ 9

У меня была та же ошибка BadRequest (400), в конце я заполняю вручную:

enter image description here

И работал на меня. Надеюсь это поможет!

Ответ 10

Я также столкнулся с такой же проблемой. В моем случае значение PartitionKey не было установлено, поэтому по умолчанию значение PartitionKey было равно null, что привело к Object reference not set to an instance of an object. exception

Убедитесь, что вы предоставили соответствующие значения для PartitionKey или RowKey, вы можете столкнуться с такой проблемой.

Ответ 11

Я исправил свои дела, и он отлично работал

Мои случаи:

  • Строка строки не в правильном формате (400).
  • Комбинация ключей разделов и строк не уникальна (409).

Ответ 12

Я получал 400 Bad Request, потому что я использовал ZRS (резервное хранилище зоны), а Google Analytics недоступна для этого типа хранилища. Я не знал, что использую Google Analytics.

Я удалил контейнер хранения и воссоздал его как GRS, и теперь он отлично работает.

Ответ 13

Я получил (400) неверный запрос, StatusMessage: неверный запрос, ErrorCode: OutOfRangeInput, когда у объекта было свойство DateTime не установлено (= DateTime.MinValue)

Ответ 14

В моем случае: я включил метаданные BLOB-объектов с именем тега, содержащим дефис.

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

Проблема была в "added-by", и позже RTFM сказал мне, что имена тегов должны соответствовать соглашениям по идентификатору С#.

Ссылка: https://docs.microsoft.com/en-us/azure/storage/blobs/storage-properties-metadata

Подчеркивание работает отлично.

Ответ 15

В моем случае я не должен добавлять PartitionKey и Rowkey в мой класс сущности. Это должно быть из базового класса. Ниже будет просто работать.

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


      public TableRunLogMessage() { }
}

Ответ 16

Если вы используете 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.

Если вы на самом деле используете С#, как делает автор этого поста; Вы можете просто установить Fiddler и установить его на перехват. По умолчанию он должен перехватывать запросы. Вам также может понадобиться доверять сертификату Fiddler или иным образом делать эквивалент узла "NODE_TLS_REJECT_UNAUTHORIZED = 0".

Ответ 17

Я получил ответ 400-BadRequest от API таблицы учетной записи хранилища Azure. Информация об исключении показала, что "Доступ к учетной записи не поддерживает http.". Я подумал, что мы должны использовать https в строке подключения, когда в конфигурации учетной записи хранения включено "Безопасная передача требуется", как показано на рисунке ниже. enter image description here

Ответ 18

В моем случае для создания новой установки класса "TableBotDataStore" (среда MS bot) мы передаем параметр "tableName" с дефисом, например "master-bot", и TableBotDataStore может иметь имена таблиц только с буквами и цифрами

Ответ 19

У меня была та же проблема, функция передавала containerNameKey как строку. ниже приведен код ошибки

container = blobClient.GetContainerReference(containerNameKey) 

Я изменил его на

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

Это сработало