десериализация xml из ответа azure


Я хочу десериализовать данные и поместить их в универсальный класс из ответа от Azure.

<ServiceResources xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/windowsazure">
<ServiceResource>
    <Name>Airport1</Name>
    <Type>Microsoft.SqlAzure.FirewallRule</Type>
    <State>Normal</State>
    <SelfLink>https://management.core.windows.net:xxx/xxx/services/sqlservers/servers/xxx/firewallrules/Airport1</SelfLink>
    <ParentLink>https://management.core.windows.net:xxxx/services/sqlservers/servers/xxx</ParentLink>
    <StartIPAddress>000.000.000.000</StartIPAddress>
    <EndIPAddress>2000.000.000.000</EndIPAddress>
  </ServiceResource>
Есть несколько объектов, которые я должен десериализовать в свой класс.
[Serializable, XmlRoot(ElementName = "ServiceResource", Namespace = "http://schemas.microsoft.com/windowsazure/")]
public class ServiceResource
{
    [XmlElement("Name")]
    public string Name { get; set; }
    [XmlElement("Type")]
    public string Type { get; set; }
    [XmlElement("State")]
    public string State { get; set; }
    [XmlElement("SelfLink")]
    public string SelfLink { get; set; }
    [XmlElement("ParentLink")]
    public string ParentLink { get; set; }
    [XmlElement("StartIPAddress")]
    public string StartIPAddress { get; set; }
    [XmlElement("EndIPAddress")]
    public string EndIPAddress { get; set; }
} 

Я попробовал несколько различных предприятий в этом и не могу его прижать. Я использовал xmlSerializer, но ударил блоки на этом.

using (var responseStreamReader = new StreamReader(webResponse.GetResponseStream()))
{
    XmlSerializer serializer = new XmlSerializer(typeof(ServiceResource));
    ServiceResource deserialized = (ServiceResource)serializer.Deserialize(responseStreamReader);

}

Любая помощь будет с благодарностью принято.

2 3

2 ответа:

Ответ

Api REST Azure возвращает список ServiceResource в XML. Поэтому вам нужно инкапсулировать это в класс. Вот вам пример.

[XmlRoot(
    ElementName = "ServiceResources",
    Namespace = "http://schemas.microsoft.com/windowsazure")]
public class ServiceResources
{
    public ServiceResources()
    {
        Items = new List<ServiceResource>();
    }

    [XmlElement("ServiceResource")]
    public List<ServiceResource> Items { get; set; }
}

public class ServiceResource
{
    [XmlElement("Name")]
    public string Name { get; set; }
    [XmlElement("Type")]
    public string Type { get; set; }
    [XmlElement("State")]
    public string State { get; set; }
    [XmlElement("SelfLink")]
    public string SelfLink { get; set; }
    [XmlElement("ParentLink")]
    public string ParentLink { get; set; }
    [XmlElement("StartIPAddress")]
    public string StartIPAddress { get; set; }
    [XmlElement("EndIPAddress")]
    public string EndIPAddress { get; set; }
}
С этими двумя классами теперь можно сделать следующее.
var response = request.GetResponse();
var message = string.Empty;
using (var responseStreamReader = new StreamReader(response.GetResponseStream()))
{
    message = responseStreamReader.ReadToEnd();
}

var textReader = new StringReader(message);
var serializer = new XmlSerializer(typeof(ServiceResources));
var serviceResources = 
    serializer.Deserialize(textReader) as ServiceResources;

Демонстрационное Консольное Приложение

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace DeserializeAzureXmlResponse
{
    class Program
    {
        private static string certificateThumbprint = "19DAED4D4ABBE0D400DC33A6D99D00D7BBB24472";
        private static string subscriptionId = "14929cfc-3501-48cf-a5c9-b24a7daaf694";
        static string sqlServerName = "mvp2015";

        static string managementUri = "https://management.core.windows.net";
        static string sqlServerApi = "services/sqlservers/servers";
        static string firewallRules = "firewallrules";

        static void Main(string[] args)
        {
            var restUri = CreateRestUri();
            var clientCert = GetX509FromPersonalStore();

            var request = (HttpWebRequest)HttpWebRequest.Create(restUri);
            request.Headers.Add("x-ms-version", "2012-03-01");
            request.ClientCertificates.Add(clientCert);

            var response = request.GetResponse();
            var message = string.Empty;
            using (var responseStreamReader = new StreamReader(response.GetResponseStream()))
            {
                message = responseStreamReader.ReadToEnd();
            }

            var textReader = new StringReader(message);
            var serializer = new XmlSerializer(typeof(ServiceResources));
            var serviceResources = serializer.Deserialize(textReader) as ServiceResources;
            foreach (var sr in serviceResources.Items)
            {
                Console.WriteLine("Name".PadRight(20) + sr.Name);
                Console.WriteLine("Type".PadRight(20) + sr.Type);
                Console.WriteLine("State".PadRight(20) + sr.State);
                Console.WriteLine("SelfLink".PadRight(20) + sr.SelfLink);
                Console.WriteLine("ParentLink".PadRight(20) + sr.ParentLink);
                Console.WriteLine("StartIP".PadRight(20) + sr.StartIPAddress);
                Console.WriteLine("EndIP".PadRight(20) + sr.EndIPAddress);
                Console.WriteLine("+++++++++++");
            }
            Console.ReadLine();
        }

        static Uri CreateRestUri()
        {
            // https://management.core.windows.net/{subscriptionID}/services/sqlservers/servers/{server}/firewallrules/
            var builder = new StringBuilder();
            builder.Append(managementUri + "/");
            builder.Append(subscriptionId + "/");
            builder.Append(sqlServerApi + "/");
            builder.Append(sqlServerName + "/");
            builder.Append(firewallRules + "/");
            var uri = new Uri(builder.ToString());
            return uri;
        }

        static X509Certificate GetX509FromPersonalStore()
        {
            // To view the personal store, press `Win + R` and then type `certmgr.msc`
            var store = new X509Store(StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly);
            var certificates = store.Certificates.Find(X509FindType.FindByThumbprint, certificateThumbprint, true);
            var certificate = certificates[0];
            store.Close();
            return certificate;
        }
    }

    [XmlRoot(
        ElementName = "ServiceResources",
        Namespace = "http://schemas.microsoft.com/windowsazure")]
    public class ServiceResources
    {
        public ServiceResources()
        {
            Items = new List<ServiceResource>();
        }

        [XmlElement("ServiceResource")]
        public List<ServiceResource> Items { get; set; }
    }

    public class ServiceResource
    {
        [XmlElement("Name")]
        public string Name { get; set; }
        [XmlElement("Type")]
        public string Type { get; set; }
        [XmlElement("State")]
        public string State { get; set; }
        [XmlElement("SelfLink")]
        public string SelfLink { get; set; }
        [XmlElement("ParentLink")]
        public string ParentLink { get; set; }
        [XmlElement("StartIPAddress")]
        public string StartIPAddress { get; set; }
        [XmlElement("EndIPAddress")]
        public string EndIPAddress { get; set; }
    }
}

Вывод

Name                My-House
Type                Microsoft.SqlAzure.FirewallRule
State               Normal
SelfLink            https://management.core.windows.net/14929cfc-35
ParentLink          https://management.core.windows.net/14929cfc-35
StartIP             123.435.234.643
EndIP               123.435.234.643
+++++++++++
Name                AllowAllWindowsAzureIps
Type                Microsoft.SqlAzure.FirewallRule
State               Normal
SelfLink            https://management.core.windows.net/14929cfc-35
ParentLink          https://management.core.windows.net/14929cfc-35
StartIP             0.0.0.0
EndIP               0.0.0.0
+++++++++++

См. Также

Можно ли десериализовать XML в List?

Список Правил Брандмауэра

Я предполагаю, что вы пытаетесь десериализовать весь граф объектов. Данный xml имеет корневой узел ServiceResources, который содержит ServiceResource. У вас есть два варианта: вы можете скопировать весь xml в классы и десриализовать; или просто получить внутренний узел ServiceResource и десериализовать эту часть.

Если вы используете первый вариант, то вам нужно будет хранить ServiceResource внутри другого класса, который имеет свойство сопоставленных коллекций с именем XmlElement, установленным в "ServiceResource", например:

[XmlType(Namespace="http://schemas.microsoft.com/windowsazure")]
[XmlRoot(Namespace="http://schemas.microsoft.com/windowsazure")]        
public class ServiceResource
{
    public string Name { get; set; }

    public string Type { get; set; }

    public string State { get; set; }

    public string SelfLink { get; set; }

    public string ParentLink { get; set; }

    public string StartIPAddress { get; set; }

    public string EndIPAddress { get; set; }

}

[XmlType(Namespace="http://schemas.microsoft.com/windowsazure")]
[XmlRoot(Namespace="http://schemas.microsoft.com/windowsazure")]
public class ServiceResources
{
    [XmlElement("ServiceResource")]
    public List<ServiceResource> ServiceResource { get; set; }
}

С этим вы должна быть возможность десериализоваться напрямую. Класс Container имеет коллекции, сопоставленные элементу ServiceResource, который будет загружать все узлы для ресурса service. Примечание: целевой тип десериализации теперь "ServiceResources", а не внутренний тип "ServiceResource"

using (var responseStreamReader = new StreamReader(webResponse.GetResponseStream()))
{
    XmlSerializer serializer = new XmlSerializer(typeof(ServiceResources));
    ServiceResources deserialized = (ServiceResources)serializer.Deserialize(responseStreamReader);

     //you can access each item in loop
    foreach(var res in deserialized.ServiceResource)
    {
       //access items e.g.
       var name = res.Name;
    }
}