Зберігання таблиці Azure повертає 400 поганих запитів


119

Я запустив це в режимі налагодження і додаю зображення з деталями винятку. Як я можу знати, що пішло не так? Я намагався вставити дані в таблицю. Чи не можете мені блакить детальніше?

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

Ця картинка насправді не допомагає, крім підтвердження помилки 400. Допомога "би" - це показати код, який ви виконали, що призвело до поганого запиту: як ви налаштували клієнт пам’яті, як налаштували таблицю, а потім перейшли вставити і т. д.
Девід Макогон

Я копіюю-вставляю код. Сподіваюся, що це допомагає
Райан

Це допоможе, якби ви сказали, який із кількох випадків не вдається. Крім того, ви, мабуть, встановлюєте деякі властивості поза цим кодом (наприклад, PartitionKey та RowKey), тому це допоможе дізнатися, що це таке і для чого вони встановлені.
Брайан Рейшл

Я помітив, що коли виняток викидається спочатку, немає опції "Переглянути деталі", але коли ви продовжуєте налагодження, і потік повертається до абонента (де виняток з’являється знову), ви можете побачити параметр Переглянути деталізацію. Звідти ви можете скористатися відповіддю @Juha Palomäki, щоб знайти помилку
raghav710

Відповіді:


148

400 Помилка означає, що зі значенням однієї з ваших властивостей щось не так. Один із способів дізнатися це - простежити запит / відповідь через Fiddler і побачити фактичні дані, що надсилаються в Windows Azure Storage.

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

Подивіться також відповідь Юхи Паломякі нижче ... Іноді є дещо корисніше повідомлення за винятком випадків, коли він пропонує (RequestInformation.ExtendedErrorInformation.ErrorMessage)


259
Для любові до Бога, якщо хтось із команди Azure прочитає це, будь ласка, змушуйте СДК повертати більше інформації, ніж помилка 400 Поганого запиту. Я поняття не маю, чому DateTime у сховищі таблиць не може мати таку ж мінімальну дату, як об’єкт .NET DateTime, але я витратив на це хороший день. На той момент, коли я перейшов до того, яке майно спричинило проблему, я теж трапився через це, що допомогло. Тепер, перш ніж я коли-небудь вставляю / оновлюю модель з DateTime для зберігання таблиць, я повинен перевірити всі властивості DateTime. НЕ ідеально ...
Майкл

8
Хоча ми це робимо, ви також не можете мати властивість enum. Мені довелося перетворити власність на Integer
Мартін

15
Мабуть, імена таблиць також не можуть мати дефіси. Мені потрібна година, щоб зрозуміти це.
Amogh Natu

4
У назвах таблиць також не може бути підкреслено .. тому я тут
Quango

2
Я думаю, що RowKey не ініціалізований з порожнім рядком, оскільки це основне значення пошуку та лише індексований стовпець ... це нагадує вам заповнити це, я б подумав .... це лише моя здогадка ... Наскільки це Імена таблиці йдуть .. прочитайте це ... blogs.msdn.microsoft.com/jmstall/2014/06/12/…
dreadeddev

129

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

Перевірте в налагоджувачі: StorageException.RequestInformation.ExtendedInformation

введіть тут опис зображення


6
Чому ця інформація не є винятком вищого рівня?
Wilko van der Veen

Для мене це підкреслило .. "Додавати крапку не підтримує емулятор" .. FML
Michiel Cornille

The specifed resource name contains invalid characters.у моєму столі таблиці були тире ... так само, як імена моєї черги ... зітхання. Сподіваємось, пошук шукає це для більшої кількості людей! см: stackoverflow.com/questions/45305556 / ...
Nateous

55

У моєму випадку це була пряма коса риса в 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();
}

4
Це було і моє питання. Ваш метод розширення працює як чемпіон!
Джеймс Вілсон

1
Мені сподобався метод розширення. Врятувало мене.
Шейх Ньютона

Альтернативний відповідь дається тут , який робить регулярний вираз заміни stackoverflow.com/a/28788382/285795
ΩmegaMan

Виправлено це для мене. У мене був переріз вперед. Здавалося, хороший персонаж для псевдоскладового ключа.
Річард

Цей спосіб розширення не видаляє кілька характерів, які заборонено. Напр .: пробіл, "(", ")" ... docs.microsoft.com/en-us/rest/api/storageservices/…
Tiago Andrade e Silva

6

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

ErrorCode: PropertyValueTooLarge ErrorMessage: Значення властивості перевищує максимально дозволений розмір (64 КБ). Якщо значенням властивості є рядок, це закодовано UTF-16, а максимальна кількість символів має бути 32K або менше.


5

ну, у моєму випадку я намагався це зробити:

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

через ContainerName SessionMaterials(як звично писати у Pascal Case і Camel Case: D) це викликало 400 поганих запитів. Отже, я просто повинен це зробити sessionmaterials. і це спрацювало.

Сподіваюся, це допоможе комусь.

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


3

в моєму випадку: ім'я контейнера було з великої літери. є обмеження при використанні символів. введіть тут опис зображення


Це стосується і імен властивостей таблиці.
Ієн Баллард


1

Документацію від MS про всі коди помилок служби Table можна знайти тут


1

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

введіть тут опис зображення

І працював на мене. Сподіваюся, це допомагає!


Ця відповідь правильна. Я витратив близько години, і це виявляє, що навіть Timestampпотрібно генерувати вручну. Це дійсно дратує.
Роман Коліада

0

Я також зіткнувся з таким же питанням. У моєму випадку значення PartitionKey не було встановлено, тому за замовчуванням значення PartitionKey було нульовим, що призвело доObject reference not set to an instance of an object. виключення

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


0

Я виправив свої справи, і це працювало чудово

Мої справи:

  1. Клавіша рядка не в правильному форматі (400).
  2. Поєднання роздільної ключа та рядкового ключа не є унікальним (409).

0

Мені надійшло 400 поганих запитів, оскільки я використовував ZRS (Зона резервного зберігання), а Analytics не доступний для цього типу пам’яті. Я не знав, що використовую Analytics.

Я видалив контейнер для зберігання і відтворив його як GRS і тепер він прекрасно працює.


0

Я отримував (400) поганий запит, статус-повідомлення: поганий запит, помилка: Код помилки: OutOfRangeInput, коли в організації було встановлено властивість DateTime не встановлено (= DateTime.MinValue)


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

Я отримав відповідь 400-BadRequest від API таблиці Azure Storage Account. Інформація про винятки показала, що "Обліковий запис, до якого доступ, не підтримує http." Я подумав, що нам потрібно використовувати https у рядку з'єднання, коли в конфігурації облікового запису пам’яті включено "Потрібна безпечна передача", як показано на зображенні нижче.введіть тут опис зображення


0

У моєму випадку для створення нового встановлення класу "TableBotDataStore" (MS bot Framework) ми передаємо параметр "tableName" з дефісом типу "master-bot", а TableBotDataStore може мати назви таблиць лише з літерами та цифрами


0

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

container = blobClient.GetContainerReference(containerNameKey) 

Я змінив це на

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

Це спрацювало

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.