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


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を確認することを除いて、その図は実際には役に立ちません。「要求する」のは、不正な要求の原因となった実行したコードを表示することです:ストレージクライアントの設定方法、テーブルの設定方法、そして実行挿入など
デビッドマコゴン2013

コードをコピーして貼り付けました。この情報がお役に立てば幸い
Ryan

いくつかのケースのどれが失敗しているのかをあなたが言ったなら、それは助けになるでしょう。また、明らかにこのコードの外部にいくつかのプロパティ(PartitionKeyやRowKeyなど)を設定しているので、それらが何であり、何に設定されているかを知るのに役立ちます。
Brian Reischl、2013

最初に例外がスローされたとき、「詳細の表示」オプションがないことに気付きましたが、デバッグを続行してフローが呼び出し元に戻ると(例外が再びポップアップします)、詳細の表示オプションが表示されます。そこから@JuhaPalomäkiの回答を使用してエラーを見つけることができます
raghav710

回答:


148

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

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

以下のJuhaPalomäkiの回答も参照してください...例外の中に少しだけ役立つメッセージが表示されることがあります(RequestInformation.ExtendedErrorInformation.ErrorMessage)


259
神の愛のために、Azureチームの誰かがこれを読んだ場合、SDKで400 Bad Requestエラーよりも多くの情報を返すようにしてください。テーブルストレージのDateTimeに.NET DateTimeオブジェクトと同じ最小日付を設定できない理由はわかりませんが、この1日で良い一日を無駄にしました。問題の原因となったプロパティを特定するまでに、この問題にも遭遇しました。ここで、テーブルストレージ用のDateTimeを使用してモデルを挿入/更新する前に、すべてのDateTimeプロパティに対してチェックを実行する必要があります。理想的ではない...
マイケル

8
ここでは、列挙型プロパティを使用することはできません。プロパティを整数に変換する必要があった
マーティン

15
明らかに、テーブル名にもハイフンを含めることはできません。それを理解するのに1時間かかった。
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 2017

私にとってこれは強調表示されました..「エミュレータによってサポートされていないblobの
追加

The specifed resource name contains invalid characters.私のテーブル名にはダッシュが含まれています...ちょうど私のキュー名と同じように...ため息。うまくいけば、検索はこれをより多くの人々のために拾います!参照:stackoverflow.com/questions/45305556/...
Nateous

55

私の場合、これは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();
}

4
これも私の問題でした。あなたの拡張メソッドはチャンピオンのように機能します!
James Wilson

1
私は拡張メソッドが大好きでした。助かりました。
ニュートンシェイク

正規表現が代わるんここに与えられた代替応答stackoverflow.com/a/28788382/285795
ΩmegaMan

私のために修正しました。スラッシュがありました。疑似複合キーに適した文字のように見えました。
リチャード

この拡張メソッドは、許可されていないいくつかの文字を削除していません。例:スペース、 "("、 ")" ... docs.microsoft.com/en-us/rest/api/storageservices/...
ティアゴ・アンドラーデ電子シルバ

6

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

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


5

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

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

ContainerName SessionMaterials(Pascal CaseおよびCamel Case:Dで書く習慣として)が原因で、400の不正なリクエストが発生していました。だから、私はそれを作らなければなりませんsessionmaterials。そしてそれは働いた。

これが誰かを助けることを願っています。

PS:-例外のhttp応答を確認するか、フィドラーを使用して要求と応答をキャプチャしてください。





1

同じBadRequest(400)エラーが発生し、最後に手動で入力しました:

ここに画像の説明を入力してください

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


この答えは正しいです。私は約1時間を無駄にしました、そしてそれTimestampは手動で生成されなければならないことさえも調整します。それは本当に迷惑です。
Roman Koliada

0

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

PartitionKeyまたはRowKeyに適切な値を指定しているかどうかを確認してください。このような問題に直面する可能性があります。


0

私は自分のケースを修正し、それはうまくいきました

私の場合:

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

0

ZRS(Zone Redundant Storage)を使用していたため、400 Bad Requestを受け取りました。このタイプのストレージではAnalyticsを使用できません。Analyticsを使用していることに気付きませんでした。

ストレージコンテナーを削除し、GRSとして再作成しましたが、正常に動作します。


0

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


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を使用する最も簡単な方法は、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_TLS_REJECT_UNAUTHORIZED = 0」と同等のことを行う必要がある場合もあります。


0

Azure Storage Account Table APIから400-BadRequest応答を受け取りました。例外情報は、「アクセスされているアカウントはhttpをサポートしていない」ことを示していました。次の図に示すように、ストレージアカウントの構成で "Secure transfer required"が有効になっている場合は、接続文字列でhttpsを使用する必要があることを理解しました。ここに画像の説明を入力してください


0

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


0

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

container = blobClient.GetContainerReference(containerNameKey) 

に変更しました

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

出来た

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.