0
votes

I am a student and I am trying to create an application that allows a user to change the instance count of there hosted service on Azure. This is done my uploading a new configuration file for the service (http://msdn.microsoft.com/en-us/library/windowsazure/ee460809.aspx). My problem is that i keep on getting the error "The remote server returned an error: (403) Forbidden" when i try to get a response in the code below.I assumed the error must be something to do with certificates but I can perform GET requests successfully and get the correct response using the same certificate that I use here. Any help is greatly appreciated.config is the new configuration file.

public void changeConfiguration(string serviceName,string deploymentSlot,string config,string deploymentName)

    {

        byte[] encodedConfigbyte = new byte[config.Length];
        encodedConfigbyte = System.Text.Encoding.UTF8.GetBytes(config);
        string encodedConfig = Convert.ToBase64String(encodedConfigbyte);

        Uri changeConfigRequestUri = new Uri("https://management.core.windows.net/" + subscriptionId + "/services/hostedservices/" + serviceName + "/deployments/" + deploymentName + "/?comp=config)");

        HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(changeConfigRequestUri);

        request.Headers.Add("x-ms-version", "2010-10-28");
        request.Method = "POST";

        string bodyText = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                          "<ChangeConfiguration xmlns=\"http://schemas.microsoft.com/windowsazure" + ">" + "<Configuration>" + encodedConfig + "</Configuration>" + "<TreatWarningsAsError>false</TreatWarningsAsError>" + "<Mode>Auto</Mode>"+"</ChangeConfiguration>";

        byte[] buf = Encoding.UTF8.GetBytes(bodyText);
        request.ContentType = "text/xml";
        request.ContentLength = buf.Length;

        StreamWriter writer = new StreamWriter(request.GetRequestStream());
        var data = Encoding.ASCII.GetBytes(buf.ToString());
        writer.Write(data);
        writer.Flush();
        writer.Close();

        X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        try
        {
            certStore.Open(OpenFlags.ReadOnly);
        }
        catch (Exception e)
        {
            if (e is CryptographicException)
            {
                Console.WriteLine("Error: The store is unreadable.");
            }
            else if (e is SecurityException)
            {
                Console.WriteLine("Error: You don't have the required permission.");
            }
            else if (e is ArgumentException)
            {
                Console.WriteLine("Error: Invalid values in the store.");
            }
            else
            {
                throw;
            }
        }


        X509Certificate2Collection certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
        certStore.Close();

        if (certCollection.Count == 0)
        {
            throw new Exception("Error: No certificate found containing thumbprint " + thumbprint);
        }

        X509Certificate2 certificate = certCollection[0];
        request.ClientCertificates.Add(certificate);


        //Error occurs in line below
        WebResponse response = (HttpWebResponse)request.GetResponse();
        try
        {
            response = request.GetResponse();
        }
       catch (WebException e)
        {
            string test = e.Message;
        }
1

1 Answers

0
votes

It looks like your content type is incorrect. This is one of the requirements for the API call.

You Have:

request.ContentType = "text/xml";

You should have:

request.ContentType = "application/xml";

Also, is there a reason you're setting your x-ms-version to "2010-10-28" instead of the latest API which is "2011-08-01";

Reference: http://msdn.microsoft.com/en-us/library/windowsazure/ee460809.aspx

EDIT: I'm also a little concerned with how you are adding your body data. It looks like you're converting your text to a UTF8 byte array and then doing a tostring on the array of bytes and reencoding that to an ascii byte array. This is odd to me. You should be able to just pass your string directly into the Write(bodyText) method of the StreamWriter. The API might not know how to decode the body data you're sending.

Try something like this...

    request.ContentType = "application/xml";

    using (var writer = new StreamWriter(request.GetRequestStream()))
    {
         writer.Write(bodyText);
    }