Azure Table storage renvoie 400 Bad Request
J'ai couru ceci en mode Débogage, et j'attache une image avec les détails de l'exception. Comment puis-je savoir quel est le problème? J'essayais d'insérer des données dans une table. Azure ne peut 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
// 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);
}
}
14 réponses
400 erreur signifie qu'il y a quelque chose de mal avec la valeur de l'une de vos propriétés. Une façon de le savoir est de tracer la demande/réponse via Fiddler et de voir les données réelles envoyées au stockage Windows Azure.
Prenant une conjecture sauvage, je suppose en jetant un coup d'œil rapide sur votre code que dans votre modèle vous avez des propriétés de type Date / Heure (OfflineTimestamp, OnlineTimestamp) et observé que dans certains scénarios l'un d'eux est initialisé avec la valeur par défaut qui est "DateTime.MinValue". Veuillez noter que la valeur minimale 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] . Veuillez voir si ce n'est pas le cas. Si c'est le cas, vous pouvez les rendre nuls afin qu'ils ne soient pas remplis avec les valeurs par défaut.
Jetez un oeil à la réponse de Juha Palomäki ci-dessous... il est parfois un peu plus utile message dans l'exception où il suggère (RequestInformation.ExtendedErrorInformation.ErrorMessage)
L'Exception StorageException contient également des informations Un peu plus détaillées sur l'erreur.
Vérifier dans le débogueur: StorageException.RequestInformation.ExtendedInformation
Dans mon cas, c'était une barre oblique dans le RowKey.
J'ai également reçu un ' OutOfRangeInput - L'une des entrées de requête est hors de portée.'erreur lors de la tentative 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 PartitionKey et RowKey propriétés:
- La barre oblique (/) personnage
- Le barre oblique inverse (\) caractère
- le signe numérique(#) caractère
- , Le point d'interrogation (?) caractère
- caractères de contrôle de U + 0000 à U + 001F , y compris:
- La tabulation horizontale (\{t[3]}) personnage
- la ligne (\N ) caractère
- le retour chariot (\R ) caractère
- 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();
}
J'ai fait face au même problème mais la raison dans mon cas était due à la taille. Après avoir creusé dans les propriétés d'exception supplémentaires (Demandeinformations.ExtendedErrorInformation), 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 encodée en UTF-16 et le nombre maximum de caractères doit être de 32K ou moins.
Dans mon cas : Le nom du conteneur était en majuscule. il y a des limites lors de l'utilisation des caractères.
Eh bien, dans mon cas, j'essayais de faire ceci:
CloudBlobContainer container = blobClient.GetContainerReference("SessionMaterials");
await container.CreateIfNotExistsAsync();
En raison de ContainerName SessionMaterials
(comme une habitude d'écriture dans le cas Pascal et le cas Camel: D) cela causait 400 mauvaises requêtes. Si,
Je dois juste le faire sessionmaterials
.
et cela a fonctionné.
J'espère que cela aide quelqu'un.
PS: - vérifiez simplement la réponse HTTP d'exception ou utilisez fiddler pour capturer la demande et la réponse.
, Parfois, c'est parce que votre partitionKey
ou rowKey
est NULL
(c'était le cas pour moi)
J'ai eu la même erreur BadRequest(400), à la fin je remplis manuellement:
Et travaillé pour moi. Espérons que cette aide!
J'ai également fait face au même genre de problème. Dans mon cas, la valeur PartitionKey N'était pas définie, donc par défaut, la valeur PartitionKey était null, ce qui a entraîné Object reference not set to an instance of an object.
exception
Vérifiez si vous fournissez les valeurs appropriées pour PartitionKey ou RowKey, vous pouvez rencontrer un tel problème.
J'ai corrigé mes cas et cela a bien fonctionné
Mes cas:
- la clé de ligne n'est pas au format correct (400).
- La combinaison de partitionkey et rowkey n'est pas unique (409).
Je recevais une requête 400 Bad car j'utilisais ZRS (zone Redundant Storage), et Analytics n'est pas disponible pour ce type de stockage. Je ne savais pas que J'utilisais Analytics.
J'ai supprimé le conteneur de stockage et recréé en tant que GRS et maintenant cela fonctionne bien.
Je recevais une (400) mauvaise requête, StatusMessage:mauvaise requête, ErrorCode:OutOfRangeInput lorsque l'entité avait une propriété DateTime non définie (=DateTime.MinValue)
Dans mon cas: j'ai inclus des métadonnées 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'identifiant C#.
Ref: https://docs.microsoft.com/en-us/azure/storage/blobs/storage-properties-metadata
Le Trait de soulignement fonctionne bien.