Создание пула пакетной службы Azure с помощью Restful API пакетной службы Azure, исключение

Я пытаюсь создать пул с помощью RESTful API. Я знаю, что есть библиотека C# для пакетного обслуживания, но чтобы программно указать идентификатор подсети, мне нужно использовать RESTful API для его создания, о чем я читал в эту статью MSDN.

URI моего поста соответствует формату

https://{account-name}.{region-id}.batch.azure.com/pools?api-version={api-version}

Код

 using (var client = new WebClient())
 {
     client.Headers[HttpRequestHeader.ContentType] = "application/json";
     client.Headers[HttpRequestHeader.Authorization] = "SharedKey <AccountName>:<Signature>";
     client.Headers[HttpRequestHeader.Date] = DateTime.UtcNow.ToString();
     try 
     {
         result = client.UploadString(baseURI, "POST", json);
     } 
     catch(Exception ex)
     {
         Console.WriteLine(ex.StackTrace);
     }
     Console.WriteLine(result);
 }

JSON, который я отправил: {"Id":"DotNetPool","vmSize":"small"}

в System.Net.WebClient.UploadDataInternal(адрес Uri, метод String, данные Byte[], WebRequest& запрос) в System.Net.WebClient.UploadString(адрес Uri, метод String, данные String)
в System.Net.WebClient .UploadString (адрес строки, метод строки, данные строки) в пакетном сервере. Загрузки\ALMTest-master\batchServer\Program.cs:строка 61

Может кто-нибудь мне помочь?


person esther fang    schedule 30.08.2016    source источник
comment
Вы решили эту проблему? Любые обновления?   -  person Bruce Chen    schedule 21.09.2016


Ответы (2)


Основываясь на предоставленном вами коде, я проверил на своей стороне и воспроизвел эту проблему. Когда вы отлаживаете код, вы можете найти подробную ошибку следующим образом:

Насколько мне известно, некоторые общие заголовки считаются ограниченными и защищены системой, и их нельзя установить или изменить в объекте WebHeaderCollection, вы можете следовать этому руководство.

В качестве простого способа я рекомендую вам использовать HttpWebRequest вместо WebClient для достижения вашей цели. Вот мой тестовый код для создания пула с использованием RESTful API.

public static void CreatePoolViaRestAPI(string baseUrl, string batchAccountName, string batchAccountKey,string jsonData)
{
    string verb = "POST";
    string apiVersion= "2016-07-01.3.1";
    string ocpDate= DateTime.UtcNow.ToString("R");
    string contentType = "application/json; odata=minimalmetadata; charset=utf-8";
    string reqUrl = string.Format("{0}/pools?api-version={1}", baseUrl, apiVersion);

    //construct the request
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(reqUrl);
    request.Method = verb;
    //Set ContentType
    request.ContentType = contentType;
    //Set ocp-date
    request.Headers.Add("ocp-date", ocpDate);
    var buffer = Encoding.UTF8.GetBytes(jsonData);
    request.ContentLength = buffer.Length;

    #region generate the signature
    string CanonicalizedHeaders = string.Format("ocp-date:{0}", ocpDate);
    string CanonicalizedResource = string.Format("/{0}/pools\napi-version:{1}", batchAccountName, apiVersion);
    string stringToSign = string.Format("{0}\n\n\n{1}\n\n{2}\n\n\n\n\n\n\n{3}\n{4}",
        verb,
        buffer.Length,
        contentType,
        CanonicalizedHeaders, CanonicalizedResource);
    //encode the stringToSign
    string signature = EncodeSignStringForSharedKey(stringToSign, batchAccountKey);
    #endregion

    //Set Authorization header
    request.Headers.Add("Authorization", string.Format("SharedKey {0}:{1}", batchAccountName, signature));
    using (var rs = request.GetRequestStream())
    {
        rs.Write(buffer, 0, buffer.Length);
    }

    //send the request and get response
    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    {
        Console.WriteLine("Response status code:{0}", response.StatusCode);
    }
}

Примечание. Свойства cloudServiceConfiguration и virtualMachineConfiguration являются взаимоисключающими, и можно указать только одно из них. Если ни один из них не указан, пакетная служба возвращает неверный запрос (400). Поэтому параметр jsonData в приведенной выше функции должен выглядеть следующим образом:

"{\"id\":\"DotNetPool\",\"vmSize\":\"small\",\"cloudServiceConfiguration\":{\"osFamily\":\"4\"}}"

ОБНОВЛЕНИЕ:

Метод кодирования stringToSign будет выглядеть следующим образом:

public string EncodeSignStringForSharedKey(string stringToSign, string accountKey)
{
    HMACSHA256 h = new HMACSHA256(Convert.FromBase64String(accountKey));
    var byteArray = h.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
    string signature = Convert.ToBase64String(byteArray);
    return signature;
}

Подробности, на которые вы можете подписаться: Аутентификация с помощью общего ключа.

person Bruce Chen    schedule 01.09.2016
comment
Где находится ваша функция EncodeSignStringForSharedKey? - person spevilgenius; 11.12.2017
comment
Я только что обновил свой ответ фрагментом кода, вы можете сослаться на него. - person Bruce Chen; 12.12.2017

Пакет SDK клиента C# для пакетной службы Azure версии 5.0.0 имеет возможность присоединения к виртуальной сети для экземпляров на основе облачной службы Windows. Вам не нужно напрямую вызывать конечную точку REST.

- Added support for joining a CloudPool to a virtual network on using the NetworkConfiguration property.

Вы можете просмотреть журнал изменений для версии 5.0.0 здесь: https://www.nuget.org/packages/Azure.Batch/5.0.0, но используйте последнюю версию.

person fpark    schedule 06.09.2016