Ok, after that last example I ended up pulling what hair I had left in my head out trying to parse the XML that got returned. I have come across this problem before but my memory being what it is I had totally forgotten about it so have written this blog post to help remind myself next time this happens.
I couldn’t seem to be able to get at the elements in the data. I was doing this:
' Parse the web response responseStream = httpResponse.GetResponseStream reader = New StreamReader(responseStream) Dim rawOutput As String = reader.ReadToEnd Dim xdoc As XDocument = XDocument.Parse(rawOutput) Dim serviceOperations = From s In xdoc.Descendants("SubscriptionOperation") Select s For Each s In serviceOperations Dim email = s.Descendants("UserEmailAddress").Value Dim operation = s.Descendants("OperationName").Value Dim opDate = s.Descendants("OperationStartedTime").Value Console.WriteLine(String.Format("User: {0} Did: {1} On: {2}", email, operation, opDate)) Next
And stepping through the code I found that ServiceOperations resolved to nothing. After a couple of hours of poking and prodding and then searching the internet I came across the solution in this post: Fetching Hosting Services Name Using Windows Azure Management API
Namespaces! Memory starts ticking over and I remember hitting this before. So here is the revised code (In full) which will get Subscription details (Basically audit information) from the Management API
Imports System.Net Imports System.Security.Cryptography.X509Certificates Imports System.IO Imports System.Text Module Module1 Sub Main() ' X.509 certificate variables Dim certStore As X509Store Dim certCollection As X509Certificate2Collection Dim certificate As X509Certificate2 ' Request and response variables Dim httpRequest As HttpWebRequest Dim httpResponse As HttpWebResponse ' Stream variables Dim responseStream As Stream Dim reader As StreamReader ' URI variable Dim requestURI As Uri Try ' specify time range Dim startTime As String = "2012-11-11" Dim endTime As String = "2012-11-13" ' The ID for the Windows Azure subscription. Dim subscriptionId As String = "{Your Subscription}" ' The thumbprint for the certificate. This certificate would have been ' previously added as a management certificate within the Windows ' Azure management portal. Dim thumbPrint As String = "{Your Thumbprint}" ' Open the certificate store for the current user. certStore = New X509Store(StoreName.My, StoreLocation.CurrentUser) certStore.Open(OpenFlags.ReadOnly) ' Find the certificate with the specified thumbprint certCollection = certStore.Certificates.Find( X509FindType.FindByThumbprint, thumbPrint, False) ' close the certificate store certStore.Close() ' Check to see if mat If certCollection.Count = 0 Then Throw New Exception("No certificate found containing thumbprint " & thumbPrint) End If ' A matching certificate was found. certificate = certCollection(0) Console.WriteLine("Using certificate with thumbprint: " & thumbPrint) ' create new request requestURI = New Uri( String.Format("https://management.core.windows.net/{0}/operations?StartTime={1}&EndTime={2}", subscriptionId, startTime, endTime) ) httpRequest = HttpWebRequest.Create(requestURI) ' add certificate to requrest httpRequest.ClientCertificates.Add(certificate) ' Specify the version information in the header httpRequest.Headers.Add("x-ms-version", "2012-03-01") httpRequest.ContentType = "application/xml" ' Make the call using the web request httpResponse = httpRequest.GetResponse ' Display the response status code Console.WriteLine("Response status code: " _ & httpResponse.StatusCode) ' Display thr request ID returned by windows azure If httpResponse.Headers IsNot Nothing Then Console.WriteLine("x-ms-request-id: " & httpResponse.Headers("x-ms-request-id")) End If ' Parse the web response responseStream = httpResponse.GetResponseStream reader = New StreamReader(responseStream) Dim rawOutput As String = reader.ReadToEnd Dim ns As XNamespace = "http://schemas.microsoft.com/windowsazure" Dim xdoc As XDocument = XDocument.Parse(rawOutput) Dim serviceOperations = From s In xdoc.Descendants(ns + "SubscriptionOperation") Select s For Each s In serviceOperations Dim email = s.Descendants(ns + "UserEmailAddress").Value Dim operation = s.Descendants(ns + "OperationName").Value Dim opDate = s.Descendants(ns + "OperationStartedTime").Value Console.WriteLine(String.Format("User: {0} Did: {1} On: {2}", email, operation, opDate)) Next httpResponse.Close() responseStream.Close() reader.Close() Console.ReadKey() Catch ex As Exception Console.WriteLine("Error encountered: " & ex.Message) Console.ReadKey() System.Environment.Exit(1) Finally System.Environment.Exit(0) End Try End Sub End Module
This can be used as an example to pull audit information from Azure. I hope this helps others not make my silly mistake ;-)
P.s. I hope you like the new theme. Thanks to the above blog post (Debugmode.net) for showing it to me. It makes reading source code much better on wider monitors.
Image may be NSFW.
Clik here to view.
Clik here to view.
