Der Azure-Tabellenspeicher gibt 400 Bad Request zurück

119

Ich habe dies im Debug-Modus ausgeführt und ein Bild mit den Details der Ausnahme angehängt. Wie kann ich wissen, was schief gelaufen ist? Ich habe versucht, Daten in eine Tabelle einzufügen. Kann Azure mir nicht mehr Details geben?

Hinweis: Der Speicher befindet sich unter Windows Azure und nicht auf meinem Computer. Die Tabellen wurden erstellt, aber ich erhalte diesen Fehler beim Einfügen von Daten

Geben Sie hier die Bildbeschreibung ein

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

und hier ist der Einfügecode:

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);
    }
}
Ryan
quelle
Dieses Bild hilft nicht wirklich, abgesehen von der Bestätigung des Fehlers 400. Würde "würde" helfen, den Code anzuzeigen, den Sie ausgeführt haben, der zu der fehlerhaften Anforderung geführt hat: Wie Sie den Speicherclient eingerichtet haben, wie Sie die Tabelle eingerichtet haben, und dann ging es weiter einfügen usw.
David Makogon
Ich habe den Code kopiert und eingefügt. Hoffe das hilft
Ryan
Es wäre hilfreich, wenn Sie sagen würden, welcher der verschiedenen Fälle fehlschlägt. Außerdem legen Sie anscheinend einige Eigenschaften außerhalb dieses Codes fest (z. B. PartitionKey und RowKey), sodass es hilfreich ist, zu wissen, was diese sind und auf was sie eingestellt sind.
Brian Reischl
Ich habe festgestellt, dass es beim ersten Auslösen der Ausnahme keine Option "Detail anzeigen" gibt. Wenn Sie jedoch mit dem Debuggen fortfahren und der Datenfluss zum Aufrufer zurückkehrt (wo die Ausnahme erneut angezeigt wird), wird die Option Detail anzeigen angezeigt. Von dort aus können Sie die Antwort von @Juha Palomäki verwenden, um den Fehler zu finden
raghav710

Antworten:

148

400 Fehler bedeutet, dass mit dem Wert einer Ihrer Eigenschaften etwas nicht stimmt. Eine Möglichkeit, dies herauszufinden, besteht darin, die Anforderung / Antwort über Fiddler zu verfolgen und die tatsächlichen Daten anzuzeigen, die an Windows Azure Storage gesendet werden.

Ich gehe davon aus, dass Sie in Ihrem Modell einige Eigenschaften vom Typ Datum / Uhrzeit (OfflineTimestamp, OnlineTimestamp) haben und festgestellt haben, dass in bestimmten Szenarien eine davon mit dem Standardwert initialisiert wird ist " DateTime.MinValue ". Beachten Sie, dass der Mindestwert für ein Attribut vom Typ Datum / Uhrzeit der 1. Januar 1601 (UTC) in Windows Azure ist [http://msdn.microsoft.com/en-us/library/windowsazure/dd179338.aspx]. . Bitte sehen Sie, ob dies nicht der Fall ist. Wenn dies der Fall ist, können Sie sie zu nullbaren Typfeldern machen, damit sie nicht mit den Standardwerten gefüllt werden.

Schauen Sie sich auch die Antwort von Juha Palomäki unten an ... manchmal gibt es eine etwas nützlichere Nachricht in der Ausnahme, in der er vorschlägt (RequestInformation.ExtendedErrorInformation.ErrorMessage)

Gaurav Mantri-AIS
quelle
259
Wenn jemand aus dem Azure-Team dies aus Liebe zu Gott liest, muss das SDK mehr Informationen zurückgeben als der Fehler "400 Bad Request". Ich habe keine Ahnung, warum die DateTime im Tabellenspeicher nicht das gleiche Mindestdatum wie das .NET DateTime-Objekt haben kann, aber ich habe einen guten Tag damit verschwendet. Als ich herausfand, welche Immobilie das Problem verursachte, passierte dies auch, was mir half. Bevor ich ein Modell mit einer DateTime für die Tabellenspeicherung einfüge / aktualisiere, muss ich jetzt alle DateTime-Eigenschaften überprüfen. NICHT ideal ...
Michael
8
Während wir gerade dabei sind, können Sie auch keine Enum-Eigenschaft haben. Ich musste Eigentum in Integer umwandeln
Martin
15
Anscheinend können Tabellennamen auch keine Bindestriche enthalten. Ich habe eine Stunde gebraucht, um das herauszufinden.
Amogh Natu
4
Tabellennamen dürfen auch keine Unterstriche haben. Deshalb bin ich hier
Quango
2
Ich stelle mir vor, RowKey wird nicht mit einer leeren Zeichenfolge initialisiert, da dies der Hauptsuchwert und nur die indizierte Spalte ist. Es soll Sie daran erinnern, es zu füllen. Ich hätte gedacht. Dies ist jedoch nur meine Vermutung Tabellennamen gehen .. lesen Sie diese ... blogs.msdn.microsoft.com/jmstall/2014/06/12/…
Dreadeddev
128

Die StorageException enthält auch etwas detailliertere Informationen zu Fehlern.

Checken Sie den Debugger ein: StorageException.RequestInformation.ExtendedInformation

Geben Sie hier die Bildbeschreibung ein

Juha Palomäki
quelle
6
Warum sind diese Informationen keine Ausnahme der obersten Ebene?
Wilko van der Veen
Für mich hervorgehoben dies .. "Append Blob nicht vom Emulator unterstützt" .. FML
Michiel Cornille
The specifed resource name contains invalid characters.Mein Tabellenname hatte Bindestriche ... genau wie meine Warteschlangennamen ... seufz. Hoffentlich nimmt die Suche dies für mehr Leute auf! siehe: stackoverflow.com/questions/45305556/…
Nateous
55

In meinem Fall war es ein Schrägstrich im RowKey .

Ich habe auch einen 'OutOfRangeInput - Einer der Anforderungseingänge liegt außerhalb des Bereichs.' Fehler beim Versuch, manuell über den Speicheremulator hinzuzufügen.

In Schlüsselfeldern nicht zugelassene Zeichen

Die folgenden Zeichen sind in Werten für die PartitionKey- und RowKey- Eigenschaften nicht zulässig :

  • Das Schrägstrichzeichen ( / )
  • Das Backslash- Zeichen ( \ )
  • Das Nummernzeichen ( # )
  • Das Fragezeichen ( ? )
  • Steuerzeichen von U + 0000 bis U + 001F , einschließlich:
    • Das horizontale Tabulatorzeichen ( \ t )
    • Das Zeilenvorschubzeichen ( \ n )
    • Das Wagenrücklaufzeichen ( \ r )
    • Steuerzeichen von U + 007F bis U + 009F

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

Ich habe eine Erweiterungsmethode geschrieben, um dies für mich zu erledigen.

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();
}
Shawn McGough
quelle
4
Das war auch mein Problem. Ihre Erweiterungsmethode funktioniert wie ein Champion!
James Wilson
1
Ich habe die Erweiterungsmethode geliebt. Rettete mich.
Newton Sheikh
Hier wird eine alternative Antwort gegeben, die einen regulären
Ausdruck
Es wurde für mich behoben. Ich hatte einen Schrägstrich. Schien wie ein guter Charakter für einen Pseudo-Compound-Schlüssel.
Richard
Diese Erweiterungsmethode entfernt nicht mehrere Zeichen, die nicht zulässig sind. ZB: Leerzeichen, "(", ")" ... docs.microsoft.com/en-us/rest/api/storageservices/…
Tiago Andrade e Silva
6

Ich hatte das gleiche Problem, aber der Grund in meinem Fall war die Größe. Nach dem Durchsuchen der zusätzlichen Ausnahmeeigenschaften (RequestInformation.ExtendedErrorInformation) wurde der Grund gefunden:

ErrorCode: PropertyValueTooLarge ErrorMessage: Der Eigenschaftswert überschreitet die maximal zulässige Größe (64 KB). Wenn der Eigenschaftswert eine Zeichenfolge ist, ist er UTF-16-codiert und die maximale Anzahl von Zeichen sollte 32 KB oder weniger betragen.

Nibras Manna
quelle
5

Nun, in meinem Fall habe ich versucht, dies zu tun:

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

Aufgrund von ContainerName SessionMaterials(als Gewohnheit, in Pascal Case und Camel Case: D zu schreiben) verursachte es 400 schlechte Anfragen. Also muss ich es einfach schaffen sessionmaterials. und es hat funktioniert.

Hoffe das hilft jemandem.

PS: - Überprüfen Sie einfach die http-Antwort der Ausnahme oder verwenden Sie den Geiger, um die Anforderung und die Antwort zu erfassen.

Jawand Singh
quelle
3

in meinem Fall: Containername war in Großbuchstaben. Bei der Verwendung von Zeichen gibt es Einschränkungen. Geben Sie hier die Bildbeschreibung ein

Ravi Anand
quelle
Dies gilt auch für Namen von Tabelleneigenschaften.
Iain Ballard
3

Manchmal liegt es daran, dass du partitionKeyoder rowKeybistNULL

(es war der Fall für mich)

Maroine Abdellah
quelle
1

Eine Dokumentation von MS zu allen Table Service-Fehlercodes finden Sie hier

huha
quelle
1

Ich hatte den gleichen BadRequest (400) Fehler, am Ende fülle ich manuell:

Geben Sie hier die Bildbeschreibung ein

Und für mich gearbeitet. Hoffe das hilft!

Gatsby
quelle
Diese Antwort ist richtig. Ich habe ungefähr eine Stunde verschwendet und es stellt sich heraus, dass sogar Timestampmanuell generiert werden muss. Es ist wirklich nervig.
Roman Koliada
0

Ich stand auch vor dem gleichen Problem. In meinem Fall wurde der PartitionKey-Wert nicht festgelegt, daher war der PartitionKey-Wert standardmäßig null, was zu einer Object reference not set to an instance of an object.Ausnahme führte

Überprüfen Sie, ob Sie die entsprechenden Werte für PartitionKey oder RowKey angeben. Möglicherweise tritt ein solches Problem auf.

Dilip Nannaware
quelle
0

Ich habe meine Fälle repariert und es hat gut funktioniert

Meine Fälle:

  1. Der Zeilenschlüssel hat nicht das richtige Format (400).
  2. Die Kombination von Partitionkey und Rowkey ist nicht eindeutig (409).
Kurkula
quelle
0

Ich habe eine 400 Bad Request erhalten, weil ich ZRS (Zone Redundant Storage) verwendet habe und Analytics für diesen Speichertyp nicht verfügbar ist. Mir war nicht bewusst, dass ich Analytics verwende.

Ich habe den Speichercontainer gelöscht und als GRS neu erstellt und jetzt funktioniert es einwandfrei.

Aidan
quelle
0

Ich habe eine (400) fehlerhafte Anforderung, StatusMessage: fehlerhafte Anforderung, Fehlercode: OutOfRangeInput erhalten, wenn für die Entität eine Eigenschaft DateTime nicht festgelegt wurde (= DateTime.MinValue).

Stig
quelle
0

In meinem Fall: Ich habe Blob-Metadaten mit einem Tag-Namen eingefügt, der einen Bindestrich enthält.

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

Der Strich "added-by"war das Problem, und später sagte mir RTFM, dass Tag-Namen den Konventionen für C # -Kennungen entsprechen müssen.

Ref: https://docs.microsoft.com/en-us/azure/storage/blobs/storage-properties-metadata

Unterstrich funktioniert gut.

Steve Friedl
quelle
0

In meinem Fall sollte ich PartitionKey und Rowkey nicht zu meiner Entitätsklasse hinzufügen. Es sollte aus der Basisklasse stammen. Unten würde einfach funktionieren.

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


      public TableRunLogMessage() { }
}
fröhlich
quelle
0

Wenn Sie NodeJS verwenden und über diesen Beitrag gestolpert sind, stellen Sie nur fest, dass Ihr Fehlerobjekt nicht so schöne detaillierte Informationen enthält. Sie können einen Proxy verwenden, um diese Details abzurufen. Da hier jedoch niemand erwähnt, wie ein Proxy verwendet werden soll.

Der einfachste Weg mit NodeJS besteht darin, zwei Umgebungsvariablen festzulegen:

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.

Wenn Sie tatsächlich C # verwenden, wie es der Autor dieses Beitrags tut; Sie können Fiddler einfach installieren und so einstellen, dass es abfängt. Standardmäßig sollte es die Anforderungen abfangen. Möglicherweise müssen Sie auch dem Fiddler-Zertifikat vertrauen oder auf andere Weise das Äquivalent von "NODE_TLS_REJECT_UNAUTHORIZED = 0" des Knotens ausführen.

Doug
quelle
0

Ich habe eine 400-BadRequest-Antwort von der Azure Storage Account Table-API erhalten. Ausnahmeinformationen zeigten, dass "Das Konto, auf das zugegriffen wird, http nicht unterstützt." Ich dachte mir, dass wir https in der Verbindungszeichenfolge verwenden müssen, wenn "Sichere Übertragung erforderlich" in der Konfiguration des Speicherkontos aktiviert ist (siehe Abbildung unten).Geben Sie hier die Bildbeschreibung ein

Kalaiselvan
quelle
0

In meinem Fall übergeben wir zum Erstellen einer neuen Instanz der Klasse "TableBotDataStore" (MS-Bot-Framework) den Parameter "tableName" mit einem Bindestrich wie "master-bot", und TableBotDataStore kann Tabellennamen nur mit Buchstaben und Zahlen enthalten

igor_bugaenko
quelle
0

Ich hatte das gleiche Problem, die Funktion übergab den containerNameKeyas-String. unten ist der Code, der Fehler gab

container = blobClient.GetContainerReference(containerNameKey) 

Ich habe es geändert in

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

Es funktionierte

Vani
quelle