【问题标题】:Serialize xml request in c# controller在 C# 控制器中序列化 xml 请求
【发布时间】:2018-11-24 02:00:47
【问题描述】:

假设我有这个用 c# 编码的类模式

public class Server
{
}

public class DataServer : Server
{
    public string ip { get; set; }
    public string name { get; set; }
    public string dataBaseName { get; set; }
}

public class ImageServer : Server
{
    public string ip { get; set; }
    public string name { get; set; }
    public int imageNumber { get; set; }
}

public class FeedServer : Server
{
    public string ip { get; set; }
    public string name { get; set; }
}


public class DataCenter
{

    public Server serverA { get; set; }

    public Server serverB { get; set; }

}

如果我在请求中得到了这个 xml

<?xml version="1.0" encoding="UTF-8"?>
<DataCenter>
   <ImageServer>
      <ip>92.82.13.1</ip>
      <name>image server</name>
      <imageNumber>50</imageNumber>
   </ImageServer>
   <FeedServer>
      <ip>82.25.87.7</ip>
      <name>feed server</name>
   </FeedServer>
</DataCenter>

这可以序列化为此类模式吗?我的课程需要什么 XMLroot、XMLattributes……?

如果我没有参考这些名称,我该如何区分应该去 serverA 和 serverB 的内容?

控制器代码

[HttpPost("CheckSlip")]
public async Task<bool> SaveServers([FromBody] DataCenter dataCenter)
{
    // code
}

数据中心为空...我无法序列化它

【问题讨论】:

    标签: c# xml asp.net-mvc serialization asp.net-core


    【解决方案1】:

    每当我必须处理 XML 序列化 时,我都会使用我的 XML 文件并将其转换为 C# 类。这个工具可能对你有用:Xml2CSharp

    之后,您可以使用此方法将您的 C# 类转换为 XML,反之亦然:Convert an object to an XML string

    关于您的问题,您只需对null 检查进行一些编码。这与编码逻辑有关,没有其他方法可以实现您的目标。

    【讨论】:

    • Visual Studio 有这个内置的:Edit|PasteSpecial。
    【解决方案2】:

    类结构和 XML 序列化属性必须反映 XML 才能正常工作。尝试手动创建这些类可能是一项相当耗时的任务。

    我发现最简单的方法是让 Visual Studio 为您生成类。 我在下面找到了一个可以在本地运行的简单示例。

    首先。复制要反序列化的 XML。然后在visual studio中添加一个新的空白类,然后选择EDIT --> Paste Special --> Paste XML as Classes

    这将在下面生成以下类

    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
        public partial class DataCenter
        {
    
            private DataCenterImageServer imageServerField;
    
            private DataCenterFeedServer feedServerField;
    
            /// <remarks/>
            public DataCenterImageServer ImageServer
            {
                get
                {
                    return this.imageServerField;
                }
                set
                {
                    this.imageServerField = value;
                }
            }
    
            /// <remarks/>
            public DataCenterFeedServer FeedServer
            {
                get
                {
                    return this.feedServerField;
                }
                set
                {
                    this.feedServerField = value;
                }
            }
        }
    
        /// <remarks/>
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
        public partial class DataCenterImageServer
        {
    
            private string ipField;
    
            private string nameField;
    
            private byte imageNumberField;
    
            /// <remarks/>
            public string ip
            {
                get
                {
                    return this.ipField;
                }
                set
                {
                    this.ipField = value;
                }
            }
    
            /// <remarks/>
            public string name
            {
                get
                {
                    return this.nameField;
                }
                set
                {
                    this.nameField = value;
                }
            }
    
            /// <remarks/>
            public byte imageNumber
            {
                get
                {
                    return this.imageNumberField;
                }
                set
                {
                    this.imageNumberField = value;
                }
            }
        }
    
        /// <remarks/>
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
        public partial class DataCenterFeedServer
        {
    
            private string ipField;
    
            private string nameField;
    
            /// <remarks/>
            public string ip
            {
                get
                {
                    return this.ipField;
                }
                set
                {
                    this.ipField = value;
                }
            }
    
            /// <remarks/>
            public string name
            {
                get
                {
                    return this.nameField;
                }
                set
                {
                    this.nameField = value;
                }
            }
        }
    

    然后创建一个 XMLSerializer 的实例并反序列化 xml。对于这个例子,我将 XML 放在一个字符串 var 中。

    var xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<DataCenter>\r\n   <ImageServer>\r\n      <ip>92.82.13.1</ip>\r\n      <name>image server</name>\r\n      <imageNumber>50</imageNumber>\r\n   </ImageServer>\r\n   <FeedServer>\r\n      <ip>82.25.87.7</ip>\r\n      <name>feed server</name>\r\n   </FeedServer>\r\n</DataCenter>";
    
                XmlSerializer s = new XmlSerializer(typeof(DataCenter));
                using (var reader = new StringReader(xml))
                {
                    var item = (DataCenter)s.Deserialize(reader);
                }
    

    您现在将拥有一个表示 XML 有效负载的对象。 希望有帮助

    【讨论】:

      【解决方案3】:

      您可以更具体地更新您的 DataCenter 类:

      public class DataCenter
      {
          public ImageServer ImageServer { get; set; }
      
          public FeedServer FeedServer { get; set; }
      }
      

      XmlSerializer 可以正确识别类并为您序列化它。

      但是,如果您试图使 DataCenter 类不可知,即它不知道它将接收哪些服务器,那么您可能会遇到一些问题。 AFAIK 序列化程序在尝试创建正确的类时不会尝试查看派生类。它只会看到Server,并且由于对象不适合该类,它不会创建它。

      如果您将serverA 名称更改为ImageServer

      public class DataCenter
      {
          public Server ImageServer { get; set; }
      
          public Server FeedServer{ get; set; }
      }
      

      然后序列化程序将为您创建一个对象,但它的类型为Server,您将无法将其转换为正确的类型。如果您在代码中尝试此操作,将导致 img 变量为 null

      [HttpPost]
      public IActionResult SaveServers([FromBody]DataCenter dataCenter)
      {
          var img = dataCenter.ImageServer as ImageServer;
      
          return Ok();
      }
      

      如果您希望 Xml 序列化程序为您完成工作,那么您需要更具体地了解您想要创建的类。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-15
        • 1970-01-01
        相关资源
        最近更新 更多