it-swarm.com.ru

Хранилище таблиц Azure возвращает 400 неверных запросов

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

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);
    }
}
101
Ryan

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

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

Взгляните также на ответ Юхи Паломяки ниже ... иногда есть несколько более полезное сообщение в исключении, в котором он предлагает (RequestInformation.ExtendedErrorInformation.ErrorMessage)

127
Gaurav Mantri

StorageException также содержит чуть более подробную информацию об ошибке. 

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

enter image description here

103
Juha Palomäki

В моем случае это косая черта в 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();
}
44
Shawn

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

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

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

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

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

3
Jawand Singh

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

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

3
Nibras Manna

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

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

3
Maroine Abdellah

в моем случае : Название контейнера было прописным. Есть ограничения при использовании символов. enter image description here

3
Ravi Anand

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

 enter image description here

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

1
gatsby

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

1
huha

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

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


      public TableRunLogMessage() { }
}
0
merry

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

0
Stig

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

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

0
Dilip Nannaware

Я получил 400 неверных запросов, потому что я использовал ZRS (Zone Redundant Storage), а аналитика для этого типа хранилища недоступна. Я не знал, что я использую аналитику. 

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

0
Aidan

В моем случае: я включил метаданные 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
Steve Friedl

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

0
Kalaiselvan

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

0
Doug

Я исправил свои дела, и это работало нормально

Мои дела:

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