Azure 테이블 저장소가 400 잘못된 요청을 반환합니다.


119

나는 이것을 디버그 모드에서 실행했고 예외의 세부 사항이있는 이미지를 첨부합니다. 무엇이 잘못되었는지 어떻게 알 수 있습니까? 테이블에 데이터를 삽입하려고했습니다. azure가 더 자세한 정보를 제공 할 수 없나요?

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을 확인하는 것 외에는 "실제로"도움이 될 것입니다. 잘못된 요청을 초래 한 실행 된 코드를 표시하는 것입니다. 스토리지 클라이언트 설정 방법, 테이블 설정 방법, 그리고 등, 삽입
데이비드 Makogon에게

코드를 복사하여 붙여 넣었습니다. 이것이 도움이되기를 바랍니다
Ryan

몇 가지 사례 중 어느 것이 실패했는지 말하면 도움이 될 것입니다. 또한이 코드 외부에서 일부 속성 (예 : PartitionKey 및 RowKey)을 설정하고 있으므로 해당 속성과 설정 대상을 파악하는 데 도움이됩니다.
Brian Reischl 2013

Exception이 먼저 발생하면 "View Detail"옵션이 없지만 디버깅을 계속하고 흐름이 호출자에게 돌아 가면 (예외가 다시 팝업되는) View Detail 옵션을 볼 수 있습니다. 거기에서 오류 찾기 위해 @Juha Palomäki의 대답을 사용할 수 있습니다
raghav710

답변:


148

400 오류는 속성 중 하나의 값에 문제가 있음을 의미합니다. 알아내는 한 가지 방법은 Fiddler를 통해 요청 / 응답을 추적하고 Windows Azure Storage로 전송되는 실제 데이터를 확인하는 것입니다.

대략적으로 추측 해보면 모델에 날짜 / 시간 유형 속성 (OfflineTimestamp, OnlineTimestamp)이 있고 특정 시나리오에서 그중 하나가 기본값으로 초기화되는 것을 관찰 한 것으로 코드를 훑어 보면서 가정하고 있습니다. " DateTime.MinValue "입니다. 날짜 / 시간 유형 속성에 허용 되는 최소값 은 Windows Azure에서 1601 년 1 월 1 일 (UTC) 입니다 . [http://msdn.microsoft.com/en-us/library/windowsazure/dd179338.aspx] . 그렇지 않은지 확인하십시오. 이 경우 기본값으로 채워지지 않도록 nullable 형식 필드를 만들 수 있습니다.

아래 Juha Palomäki의 답변도 살펴보십시오 ... 때로는 그가 제안하는 예외에 약간 더 유용한 메시지가 있습니다 (RequestInformation.ExtendedErrorInformation.ErrorMessage)


259
하나님의 사랑을 위해 Azure 팀의 누군가가 이것을 읽으면 SDK가 400 Bad Request 오류보다 더 많은 정보를 반환하도록하십시오. 테이블 저장소의 DateTime이 .NET DateTime 개체와 동일한 최소 날짜를 가질 수없는 이유를 모르겠지만 좋은 하루를 낭비했습니다. 어떤 재산이 문제를 일으켰는지 파악했을 때이 문제도 발생하여 도움이되었습니다. 이제 테이블 저장을 위해 DateTime을 사용하여 모델을 삽입 / 업데이트하기 전에 모든 DateTime 속성에 대해 검사를 실행해야합니다. 이상적이지 않습니다 ...
Michael

8
우리가 그것에있는 동안, 당신은 열거 형 속성도 가질 수 없습니다. 나는 재산을 정수로
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

나를 위해이 강조 .. "추가]의 덩어리가 에뮬레이터에서 지원하지".. FML
미키 엘 Cornille

The specifed resource name contains invalid characters.내 테이블 이름에 대시가 있습니다 ... 내 대기열 이름처럼 ... 한숨. 바라건대 검색하면 더 많은 사람들을 찾을 수 있습니다! 참조 : stackoverflow.com/questions/45305556/…
Nateous

55

제 경우에는 RowKey의 슬래시 였습니다. .

또한 'OutOfRangeInput-요청 입력 중 하나가 범위를 벗어났습니다.'를 받았습니다. 스토리지 에뮬레이터를 통해 수동으로 추가하려고 할 때 오류가 발생했습니다.

키 필드에서 허용되지 않는 문자

다음 문자는 PartitionKeyRowKey 속성 값에 허용되지 않습니다 .

  • 슬래시 ( / ) 문자
  • 백 슬래시 ( \ ) 문자
  • 숫자 기호 ( # ) 문자
  • 물음표 ( ? ) 문자
  • 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
나는 확장 방법을 좋아했습니다. 나를 구했다.
Newton Sheikh

정규식을 대체하는 여기에 주어진 대체 응답은 stackoverflow.com/a/28788382/285795
ΩmegaMan

나를 위해 고쳤습니다. 나는 슬래시를 가졌습니다. 의사 복합 키에 대한 좋은 캐릭터처럼 보였습니다.
리처드

이 확장 방법은 허용되지 않는 여러 문자를 제거하지 않습니다. 예 : 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. 그리고 그것은 작동했습니다.

이것이 도움이되기를 바랍니다.

추신 :-예외 http 응답을 확인하거나 피들러를 사용하여 요청 및 응답을 캡처하십시오.


3

제 경우에는 컨테이너 이름이 대문자였습니다. 문자를 사용할 때 제한이 있습니다. 여기에 이미지 설명 입력


이것은 테이블 속성 이름에도 적용됩니다.
Iain Ballard



1

마지막에 수동으로 채우는 동일한 BadRequest (400) 오류가 발생했습니다.

여기에 이미지 설명 입력

그리고 나를 위해 일했습니다. 도움이 되었기를 바랍니다!


정답입니다. 나는 약 한 시간을 낭비했고 심지어 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 잘못된 요청을 받았는데이 유형의 스토리지에는 Analytics를 사용할 수 없습니다. Analytics를 사용하고 있다는 사실을 몰랐습니다.

스토리지 컨테이너를 삭제하고 GRS로 다시 생성했는데 이제 제대로 작동합니다.


0

엔터티에 DateTime 속성이 설정되어 있지 않을 때 (400) Bad Request, StatusMessage : Bad Request, ErrorCode : OutOfRangeInput이 발생했습니다 (= 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

Azure Storage 계정 테이블 API에서 400-BadRequest 응답을 받았습니다. 예외 정보에 "액세스중인 계정이 http를 지원하지 않습니다."라고 표시되었습니다. 아래 이미지와 같이 스토리지 계정 구성에서 "보안 전송 필요"가 활성화 된 경우 연결 문자열에 https를 사용해야한다고 생각했습니다.여기에 이미지 설명 입력


0

필자의 경우 "TableBotDataStore"클래스 (MS 봇 프레임 워크)의 새 설치를 만들기 위해 "master-bot"과 같은 하이픈이있는 "tableName"매개 변수를 전달하고 TableBotDataStore는 문자와 숫자로만 테이블 이름을 가질 수 있습니다.


0

나는 같은 문제가 있었고 함수는 containerNameKeyas 문자열 을 전달했습니다 . 아래는 오류를 준 코드입니다.

container = blobClient.GetContainerReference(containerNameKey) 

나는 그것을

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

효과가 있었다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.