ที่เก็บตาราง Azure ส่งคืน 400 คำขอที่ไม่ถูกต้อง


119

ฉันรันสิ่งนี้ในโหมดดีบักและแนบรูปภาพพร้อมรายละเอียดของข้อยกเว้น ฉันจะรู้ได้อย่างไรว่าเกิดอะไรขึ้น? ฉันพยายามใส่ข้อมูลในตาราง สีฟ้าไม่สามารถให้รายละเอียดเพิ่มเติมได้หรือไม่?

ข้อสังเกต: ที่เก็บข้อมูลอยู่บน 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 การ "จะ" ช่วยได้คือการแสดงรหัสที่คุณเรียกใช้ซึ่งส่งผลให้เกิดคำขอที่ไม่ถูกต้อง: คุณตั้งค่าไคลเอ็นต์หน่วยเก็บข้อมูลอย่างไรคุณตั้งค่าตารางอย่างไรจากนั้นไป แทรก ฯลฯ
เดวิดมาโก

ฉันคัดลอกวางรหัส หวังว่านี่จะช่วยได้
Ryan

จะช่วยได้หากคุณบอกว่ากรณีใดในหลายกรณีที่ล้มเหลว นอกจากนี้คุณกำลังตั้งค่าคุณสมบัติบางอย่างนอกรหัสนี้ (เช่น PartitionKey และ RowKey) ดังนั้นจึงจะช่วยให้ทราบว่าสิ่งเหล่านี้คืออะไรและตั้งค่าอะไร
Brian Reischl

ฉันสังเกตเห็นว่าเมื่อ Exception ถูกโยนออกไปก่อนจะไม่มีตัวเลือก "View Detail" แต่เมื่อคุณทำการดีบักต่อไปและโฟลว์จะกลับไปที่ผู้โทร (ซึ่งข้อยกเว้นจะปรากฏขึ้นอีกครั้ง) คุณจะเห็นตัวเลือก View Detail จากนั้นคุณสามารถใช้คำตอบของ @Juha Palomäkiเพื่อค้นหาข้อผิดพลาด
raghav710

คำตอบ:


149

ข้อผิดพลาด 400 หมายความว่ามีบางอย่างผิดปกติกับค่าของคุณสมบัติอย่างใดอย่างหนึ่งของคุณ วิธีหนึ่งในการค้นหาคือการติดตามคำขอ / การตอบกลับผ่าน Fiddler และดูข้อมูลจริงที่ส่งไปยัง Windows Azure Storage

ลองเดาดูฉันคิดว่าโดยการดูโค้ดของคุณอย่างรวดเร็วว่าในโมเดลของคุณคุณมีคุณสมบัติประเภทวันที่ / เวลา (OfflineTimestamp, OnlineTimestamp) และสังเกตว่าในบางสถานการณ์หนึ่งในนั้นเริ่มต้นด้วยค่าเริ่มต้นซึ่ง คือ " DateTime.MinValue " โปรดทราบว่าค่าต่ำสุดที่อนุญาตสำหรับวันที่ / เวลาประเภทแอตทริบิวต์เป็น 1 มกราคม 1601 (UTC)ใน Windows Azure [http://msdn.microsoft.com/en-us/library/windowsazure/dd179338.aspx] โปรดดูว่าไม่ใช่กรณีนี้หรือไม่ หากเป็นเช่นนั้นคุณสามารถกำหนดให้เป็นช่องประเภทที่ว่างได้เพื่อที่จะไม่ได้รับค่าเริ่มต้น

ลองดูคำตอบของ Juha Palomäkiด้านล่างนี้เช่นกัน ... บางครั้งมีข้อความที่มีประโยชน์มากกว่าเล็กน้อยในข้อยกเว้นที่เขาแนะนำ (RequestInformation.ExtendedErrorInformation.ErrorMessage)


260
สำหรับความรักของพระเจ้าหากมีใครบางคนจากทีม Azure อ่านสิ่งนี้โปรดให้ SDK ส่งคืนข้อมูลมากกว่าข้อผิดพลาด 400 คำขอที่ไม่ถูกต้อง ฉันไม่รู้ว่าทำไม DateTime ในที่จัดเก็บตารางไม่สามารถมีวันที่ต่ำสุดเหมือนกับออบเจ็กต์. NET DateTime แต่ฉันเสียวันที่ดีไปกับวันนี้ เมื่อถึงเวลาที่ทรัพย์สินที่ทำให้เกิดปัญหาฉันก็เจอปัญหานี้เช่นกันซึ่งช่วยได้ ตอนนี้ก่อนที่ฉันจะแทรก / อัปเดตโมเดลด้วย DateTime สำหรับการจัดเก็บตารางฉันต้องเรียกใช้การตรวจสอบคุณสมบัติ DateTime ทั้งหมด ไม่เหมาะ ...
Michael

8
ในขณะที่เราอยู่ที่นั่นคุณไม่สามารถมีคุณสมบัติ enum ได้เช่นกัน ฉันต้องแปลงคุณสมบัติเป็น Integer
Martin

15
เห็นได้ชัดว่าชื่อตารางไม่สามารถมียัติภังค์ได้เช่นกัน ฉันใช้เวลาหนึ่งชั่วโมงในการคิดออก
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

สำหรับฉันสิ่งนี้เน้น .. "Append blob not supported by emulator" .. FML
Michiel Cornille

The specifed resource name contains invalid characters.ชื่อโต๊ะของฉันมีขีดกลาง ... เหมือนกับชื่อคิวของฉัน ... ถอนหายใจ หวังว่าการค้นหาจะช่วยให้ผู้คนจำนวนมากขึ้น! ดู: stackoverflow.com/questions/45305556/…
Nateous

55

ในกรณีของฉันมันเป็นทับในRowKey

ฉันยังได้รับ 'OutOfRangeInput - หนึ่งในอินพุตคำขออยู่นอกช่วง' เกิดข้อผิดพลาดเมื่อพยายามเพิ่มด้วยตนเองผ่านโปรแกรมจำลองการจัดเก็บข้อมูล

ไม่อนุญาตให้ใช้อักขระในฟิลด์คีย์

ไม่อนุญาตให้ใช้อักขระต่อไปนี้ในค่าสำหรับ คุณสมบัติPartitionKeyและRowKey :

  • อักขระสแลช ( / ) ไปข้างหน้า
  • อักขระแบ็กสแลช ( \ )
  • เครื่องหมายตัวเลข ( # ) อักขระ
  • เครื่องหมายคำถาม ( ? ) อักขระ
  • ควบคุมอักขระจากU + 0000 ถึง U + 001Fรวมถึง:
    • แท็บแนวนอน ( \ t ) อักขระ
    • อักขระ linefeed ( \ n )
    • อักขระcarriage return ( \ 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
ฉันชอบวิธีการขยาย ช่วยฉันไว้
Newton Sheikh

การตอบสนองทางเลือกที่กำหนดไว้ที่นี่ซึ่ง regex จะแทนที่stackoverflow.com/a/28788382/285795
ΩmegaMan

แก้ไขให้ฉัน ฉันมีเครื่องหมายทับ ดูเหมือนจะเป็นตัวละครที่ดีสำหรับคีย์ผสมหลอก
richard

วิธีการขยายนี้ไม่ได้ลบอักขระหลายตัวที่ไม่ได้รับอนุญาต เช่น: space, "(", ")" ... docs.microsoft.com/en-us/rest/api/storageservices/…
Tiago Andrade e Silva

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 ข้อยกเว้นหรือใช้ fiddler เพื่อบันทึกคำขอและการตอบกลับ


3

ในกรณีของฉันชื่อคอนเทนเนอร์เป็นอักษรตัวใหญ่ มีข้อ จำกัด เมื่อใช้ตัวอักษร ใส่คำอธิบายภาพที่นี่


สิ่งนี้ใช้กับชื่อคุณสมบัติของตารางด้วย
Iain Ballard



1

ฉันมีข้อผิดพลาด BadRequest (400) เดียวกันในตอนท้ายฉันกรอกด้วยตนเอง:

ใส่คำอธิบายภาพที่นี่

และทำงานให้ฉัน หวังว่านี่จะช่วยได้!


คำตอบนี้ถูกต้อง ฉันเสียเวลาประมาณหนึ่งชั่วโมงและได้รับการตอบรับว่าTimestampต้องสร้างด้วยตนเอง มันน่ารำคาญจริงๆ
Roman Koliada

0

ฉันก็ประสบปัญหาแบบเดียวกัน ในกรณีของฉันไม่ได้ตั้งค่า PartitionKey ดังนั้นโดยค่าเริ่มต้น PartitionKey จึงเป็นโมฆะซึ่งส่งผลให้เกิดObject reference not set to an instance of an object.ข้อยกเว้น

ตรวจสอบว่าคุณระบุค่าที่เหมาะสมสำหรับ PartitionKey หรือ RowKey คุณอาจประสบปัญหาดังกล่าว


0

ฉันแก้ไขเคสของฉันแล้วและมันก็ใช้ได้ดี

กรณีของฉัน:

  1. คีย์แถวไม่อยู่ในรูปแบบที่ถูกต้อง (400)
  2. การรวมกันของพาร์ติชันคีย์และคีย์แถวไม่ซ้ำกัน (409)

0

ฉันได้รับ 400 คำขอที่ไม่ถูกต้องเนื่องจากฉันใช้ ZRS (Zone Redundant Storage) และ Analytics ไม่สามารถใช้ได้กับพื้นที่เก็บข้อมูลประเภทนี้ ฉันไม่รู้ว่าฉันกำลังใช้ Analytics

ฉันลบที่เก็บข้อมูลและสร้างใหม่เป็น GRS และตอนนี้ก็ใช้งานได้ดี


0

ฉันได้รับคำขอที่ไม่ถูกต้อง (400), StatusMessage: Bad Request, ErrorCode: OutOfRangeInput เมื่อเอนทิตีมีคุณสมบัติ DateTime not set (= DateTime.MinValue)


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 คือการตั้งค่าตัวแปรสภาพแวดล้อมสองตัว:

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

ฉันได้รับคำตอบ 400-BadRequest จาก Azure Storage Account Table API ข้อมูลข้อยกเว้นแสดงให้เห็นว่า "บัญชีที่กำลังเข้าถึงไม่รองรับ http" ฉันคิดว่าเราต้องใช้ https ในสตริงการเชื่อมต่อเมื่อเปิดใช้งาน "Secure transfer required" ในการกำหนดค่าบัญชีพื้นที่เก็บข้อมูลดังที่แสดงในภาพด้านล่างใส่คำอธิบายภาพที่นี่


0

ในกรณีของฉันสำหรับการสร้างการติดตั้งใหม่ของคลาส "TableBotDataStore" (เฟรมเวิร์กของบอท MS) เราส่งผ่านพารามิเตอร์ "tableName" ด้วยยัติภังค์เช่น "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.