web-dev-qa-db-fra.com

Le stockage de la table Azure renvoie 400 requêtes incorrectes

J'ai exécuté cela en mode débogage et je joint une image avec les détails de l'exception. Comment puis-je savoir ce qui s'est mal passé? J'essayais d'insérer des données dans une table. Azure ne peut-il pas me donner plus de détails?

Obs: Le stockage est sur Windows Azure pas sur ma machine. Les tables ont été créées, mais j'obtiens cette erreur lors de l'insertion de données

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

et voici le code d'insertion:

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 Erreur signifie qu'il y a un problème avec la valeur de l'une de vos propriétés. Une façon de le savoir consiste à suivre la demande/réponse via Fiddler et à voir les données réelles envoyées à Windows Azure Storage. 

Prenant une conjecture sauvage, je suppose en jetant un coup d'œil sur votre code que dans votre modèle, vous avez des propriétés de type Date/Heure (OfflineTimestamp, OnlineTimestamp) et que, dans certains scénarios, l'un d'entre eux est initialisé avec la valeur par défaut qui est "DateTime.MinValue". Notez que la valeur minimale de autorisée pour un attribut de type Date/Heure est le 1er janvier 1601 (UTC) dans Windows Azure [http://msdn.Microsoft.com/en-us/library/windowsazure/ dd179338.aspx] . S'il vous plaît voir si ce n'est pas le cas. Si tel est le cas, vous pouvez alors définir des champs de type Nullable afin qu'ils ne soient pas renseignés avec les valeurs par défaut.

Regardez aussi la réponse ci-dessous de Juha Palomäki ... il existe parfois un message légèrement plus utile dans l'exception où il suggère (RequestInformation.ExtendedErrorInformation.ErrorMessage)

127
Gaurav Mantri

StorageException contient également des informations un peu plus détaillées sur les erreurs. 

Archiver dans le débogueur: StorageException.RequestInformation.ExtendedInformation

enter image description here

103
Juha Palomäki

Dans mon cas, il s'agissait d'une barre oblique dans RowKey

J'ai également reçu un message 'OutOfRangeInput - Une des entrées de la demande est hors limites.' erreur en essayant d'ajouter manuellement via l'émulateur de stockage.

Caractères non autorisés dans les champs clés

Les caractères suivants ne sont pas autorisés dans les valeurs pour le Propriétés PartitionKey et RowKey:

  • La barre oblique (/)
  • La barre oblique inverse (\)
  • Le signe dièse (#)
  • Le point d'interrogation (?) Caractère
  • Caractères de contrôle de U + 0000 à U + 001F, y compris:
    • Le caractère de tabulation horizontale (\ t)
    • Le saut de ligne (\ n) caractère
    • Le caractère de retour chariot (\ r)
    • Caractères de contrôle de U + 007F à U + 009F

http://msdn.Microsoft.com/en-us/library/dd179338.aspx

J'ai écrit une méthode d'extension pour gérer cela pour moi .

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

eh bien, dans mon cas, j'essayais de faire ceci:

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

à cause de ContainerName SessionMaterials (comme habitude d'écrire dans Pascal Case et Camel Case: D), il causait 400 mauvaises requêtes. Donc, Je dois juste le faire sessionmaterials. Et cela a fonctionné.

J'espère que cela aide quelqu'un. 

PS: - Il suffit de vérifier la réponse HTTP d’exception ou d’utiliser Fiddler pour capturer demande et réponse.

3
Jawand Singh

J'ai eu le même problème mais la raison dans mon cas était due à la taille. Après avoir exploré les propriétés d'exception supplémentaires (RequestInformation.ExtendedErrorInformation), vous en avez trouvé la raison: 

ErrorCode: PropertyValueTooLarge ErrorMessage: la valeur de la propriété dépasse la taille maximale autorisée (64 Ko). Si la valeur de la propriété est une chaîne, elle est codée en UTF-16 et le nombre maximal de caractères doit être inférieur ou égal à 32 Ko.

3
Nibras Manna

Parfois, c'est parce que votre partitionKey ou rowKey est NULL

(c'était le cas pour moi)

3
Maroine Abdellah

dans mon cas : Le nom du conteneur était en majuscule. il y a des limitations lors de l'utilisation des caractères.  enter image description here

3
Ravi Anand

J'ai eu la même erreur BadRequest (400), à la fin je remplis manuellement:

 enter image description here

Et a travaillé pour moi. J'espère que cela t'aides!

1
gatsby

Une documentation de MS sur tous les codes d'erreur du service de table est disponible ici

1
huha

Dans mon cas, je ne devrais pas ajouter PartitionKey et Rowkey dans ma classe d'entité. Il devrait être de la classe de base. Ci-dessous serait juste travailler.

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


      public TableRunLogMessage() { }
}
0
merry

Je recevais une (400) demande incorrecte, StatusMessage: demande incorrecte, ErrorCode: OutOfRangeInput lorsque l'entité avait une propriété DateTime non définie (= DateTime.MinValue)

0
Stig

J'ai également rencontré le même genre de problème. Dans mon cas, la valeur PartitionKey n'était pas définie. Par défaut, la valeur PartitionKey était null, ce qui a entraîné une exception Object reference not set to an instance of an object.

Vérifiez si vous fournissez les valeurs appropriées pour PartitionKey ou RowKey, vous pouvez être confronté à un tel problème.

0
Dilip Nannaware

J'obtenais une demande 400 bad parce que j'utilisais ZRS (Zone Redundant Storage), et Analytics n'est pas disponible pour ce type de stockage. Je ne savais pas que j'utilisais Google Analytics. 

J'ai supprimé le conteneur de stockage et recréé en tant que GRS et maintenant cela fonctionne bien.

0
Aidan

J'ai eu le même problème, la fonction passait le containerNameKey en tant que chaîne. ci-dessous est le code qui a donné une erreur

container = blobClient.GetContainerReference(containerNameKey) 

Je l'ai changé pour

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

Ça a marché

0
Vani

Dans mon cas, pour créer une nouvelle instance de la classe "TableBotDataStore" (infrastructure MS bot), nous passons le paramètre "tableName" avec un trait d'union comme "master-bot" et TableBotDataStore peut uniquement avoir des noms de table avec des lettres et des chiffres.

0
igor_bugaenko

Dans mon cas: j'ai inclus des métadonnées de blob avec un nom de balise contenant un trait d'union.

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

Le tiret dans "added-by" était le problème, et plus tard, RTFM m'a dit que les noms de balises doivent être conformes aux conventions d'identificateur C #.

Réf.: https://docs.Microsoft.com/en-us/Azure/storage/blobs/storage-properties-metadata

Le soulignement fonctionne bien.

0
Steve Friedl

J'ai reçu une réponse 400-BadRequest de l'API Azure Storage Account Table. Les informations sur les exceptions indiquent que "le compte auquel on accède ne prend pas en charge http.". J'ai pensé que nous devions utiliser https dans la chaîne de connexion lorsque "Transfert sécurisé requis" est activé dans la configuration du compte de stockage, comme indiqué dans l'image ci-dessous.  enter image description here 

0
Kalaiselvan

Si vous utilisez NodeJS et que vous avez trébuché sur ce post, seulement pour constater que vous n'obtenez pas cette belle information détaillée dans votre objet d'erreur; vous pouvez utiliser un proxy pour obtenir ces détails. Cependant, puisque personne n’indique ici comment utiliser un proxy.

La méthode la plus simple avec NodeJS consiste à définir deux variables d’environnement:

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.

Si vous utilisez réellement C #, comme le fait l'auteur de ce post; vous pouvez simplement installer Fiddler et le configurer pour l’intercepter. Par défaut, il devrait intercepter les demandes. Vous devrez peut-être également faire confiance au certificat de Fiddler ou faire l'équivalent de "NODE_TLS_REJECT_UNAUTHORIZED = 0" du noeud.

0
Doug

J'ai réparé mes valises et cela a bien fonctionné

Mes cas:

  1. La clé de ligne n'est pas au bon format (400).
  2. La combinaison partitionkey et rowkey n'est pas unique (409).
0
Kurkula