web-dev-qa-db-ja.com

Azureテーブルストレージが400 Bad Requestを返します

これをデバッグモードで実行し、例外の詳細を含む画像を添付します。何が間違っていたのかを知るにはどうすればよいですか?テーブルにデータを挿入しようとしていました。 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);
    }
}
110
Ryan

400エラーは、いずれかのプロパティの値に問題があることを意味します。見つける方法の1つは、Fiddlerを介して要求/応答をトレースし、Windows Azureストレージに送信される実際のデータを確認することです。

ワイルドな推測をして、コードをひと目見て、モデルに日付/時刻型のプロパティ(OfflineTimestamp、OnlineTimestamp)があり、特定のシナリオではそのうちの1つがデフォルト値で初期化されることに気づいたと思います「DateTime.MinValue」です。日付/時刻型の属性に許可される最小値は、Windows Azureでは1601年1月1日(UTC)であることに注意してください [http: //msdn.Microsoft.com/en-us/library/windowsazure/dd179338.aspx] 。そうでない場合はご覧ください。その場合、デフォルト値が入力されないように、null許容型フィールドにすることができます。

以下のJuhaPalomäkiの回答もご覧ください...例外の中に、彼が示唆するわずかに役立つメッセージがある場合があります(RequestInformation.ExtendedErrorInformation.ErrorMessage)

132
Gaurav Mantri

StorageExceptionには、エラーに関するもう少し詳細な情報も含まれています。

デバッガーでチェックイン:StorageException.RequestInformation.ExtendedInformation

enter image description here

113
Juha Palomäki

私の場合、RowKeyのスラッシュでした。

また、「OutOfRangeInput-要求入力の1つが範囲外です」も受け取りました。ストレージエミュレータを介して手動で追加しようとするとエラーが発生します。

キーフィールドで許可されていない文字

次の文字は、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();
}
47
Shawn

まあ、私の場合、私はこれをやろうとしていました:

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

containerName SessionMaterials(Pascal CaseとCamel Case:Dで書く習慣として)のために、400の悪いリクエストを引き起こしていました。だから、私はそれをsessionmaterialsにする必要があります。そしてそれは働いた。

これが何らかの助けになることを願っています。

PS:-例外HTTP応答を確認するか、フィドラーを使用して要求と応答をキャプチャします。

5
Jawand Singh

私は同じ問題に直面しましたが、私の場合の理由はサイズによるものでした。追加の例外プロパティ(RequestInformation.ExtendedErrorInformation)を掘り下げた後、理由が見つかりました。

ErrorCode:PropertyValueTooLarge ErrorMessage:プロパティ値が最大許容サイズ(64KB)を超えています。プロパティ値が文字列の場合、UTF-16でエンコードされ、最大文字数は32K以下である必要があります。

4
Nibras Manna

場合によっては、partitionKeyまたはrowKeyNULLであることが原因です。

(私にとってはそうでした)

3

私の場合:コンテナ名は大文字でした。文字の使用には制限があります。 enter image description here

3
Ravi Anand

私は同じBadRequest(400)エラーがありましたが、最後に手動で入力します:

enter image description here

そして私のために働いた。お役に立てれば!

1
gatsby

すべてのテーブルサービスエラーコードに関するMSからのドキュメントを見つけることができます here

1
huha

私の場合、EntityクラスにPartitionKeyとRowkeyを追加しないでください。基本クラスからのものでなければなりません。以下はうまくいくでしょう。

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


      public TableRunLogMessage() { }
}
0
merry

エンティティにプロパティDateTimeが設定されていない(= DateTime.MinValue)とき、(400)Bad Request、StatusMessage:Bad Request、ErrorCode:OutOfRangeInputを取得していました

0
Stig

私も同じような問題に直面しました。私の場合、PartitionKeyの値は設定されていなかったため、デフォルトではPartitionKeyの値はnullであり、Object reference not set to an instance of an object.例外が発生しました。

PartitionKeyまたはRowKeyに適切な値を提供しているかどうかを確認すると、このような問題に直面する可能性があります。

0
Dilip Nannaware

ZRS(Zone Redundant Storage)を使用していたため、400 Bad Requestを受け取っていましたが、このタイプのストレージではAnalyticsを使用できません。アナリティクスを使用していることを知りませんでした。

ストレージコンテナを削除し、GRSとして再作成したところ、正常に動作するようになりました。

0
Aidan

同じ問題がありました。関数はcontainerNameKeyを文字列として渡していました。以下はエラーを与えたコードです

container = blobClient.GetContainerReference(containerNameKey) 

に変更しました

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

動いた

0
Vani

「TableBotDataStore」クラス(MSボットフレームワーク)の新しいインストールを作成する私の場合、「master-bot」のようなハイフンで「tableName」パラメーターを渡し、TableBotDataStoreは文字と数字のみでテーブル名を持つことができます

0
igor_bugaenko

私の場合:タグ名にハイフンを含む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

Azure Storage Account Table APIから400-BadRequest応答を受け取りました。例外情報は、「アクセスされているアカウントはhttpをサポートしていない」ことを示しました。下の画像に示すように、ストレージアカウントの構成で「安全な転送が必要」が有効になっている場合、接続文字列でhttpsを使用する必要があると考えました。 enter image description here

0
Kalaiselvan

NodeJSを使用していて、この投稿を偶然見つけた場合は、エラーオブジェクトにそのような詳細な情報が含まれていないことがわかります。プロキシを使用してこれらの詳細を取得できます。ただし、ここでは誰がプロキシを使用するかについて言及していないためです。

NodeJSで最も簡単な方法は、2つの環境変数を設定することです。

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
Doug

ケースを修正し、問題なく動作しました

私の場合:

  1. 行キーの形式が正しくありません(400)。
  2. Partitionkeyとrowkeyの組み合わせは一意ではありません(409)。
0
Kurkula