首页 > 解决方案 > XmlSerializerOutputFormatter 和 XmlDataContractSerializerOutputFormatter 之间的区别

问题描述

我想知道这两个序列化程序之间有什么区别。当设置接受标头=应用程序/xml。使用普通 DTO 作为返回值,首选哪一个?还请求 xml 作为响应的 api 的消费者应该使用哪个?

我正在研究aspnet core web api 3.1,构建restful api。对上述查询的任何建议/重定向都会有所帮助。

标签: c#asp.net-core-3.1output-formatting

解决方案


XmlSerializerOutputFormatter是一个在内部使用的asp.net核心输出格式化程序XmlSerializer,而在内部DataContractSerializerOutputFormatter使用DataContractSerializer

配置DataContractSerializer更灵活。例如,它支持引用检测以防止序列化程序递归序列化项目,这通常会导致无限循环。

在我自己的项目中,我更喜欢使用它,DataContractSerializerOutputFormatter因为它能够处理带有私有 setter 的属性

public string Text { get; private set; }

失败案例

Dtos项目

namespace DataContractSerializerPOC.Dtos
{
    public class Person
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }

        // Fullname can only be set from this project
        public string FullName { get; internal set; }
    }

    public class PersonService
    {
        public List<Person> GetPeople()
        {
            // Create a list of people to be serialized
            var people = new List<Person>
            {
                new Person { Id = 1, FirstName = "John", LastName = "Doe" },
                new Person { Id = 2, FirstName = "Jim", LastName = "Flix" },
                new Person { Id = 3, FirstName = "Jack", LastName = "Splick" },
            };
            
            // Set the fullname from this project
            // In some cases you may need to do this, instead of implementing a readonly property
            foreach (var person in people)
                person.FullName = $"{person.FirstName} {person.LastName}";

            return people;
        }
    }
}

控制台项目

namespace DataContractSerializerPOC
{
    class Program
    {
        static void Main(string[] args)
        {
            var personService = new PersonService();
            var people = personService.GetPeople();

            var writer = new StringWriter();
            var serializer = new XmlSerializer(typeof(List<Person>));
            serializer.Serialize(writer, people);
        }
    }
}

结果

无法反序列化类型,因为它包含没有公共设置器的属性

使用 DataContractSerializer 的工作案例

Dtos项目

namespace DataContractSerializerPOC.Dtos
{
    [DataContract]
    public class Person
    {
        [DataMember]
        public int Id { get; set; }
        [DataMember]
        public string FirstName { get; set; }
        [DataMember]
        public string LastName { get; set; }

        // Fullname can only be set from this project
        [DataMember]
        public string FullName { get; internal set; }
    }

    public class PersonService
    {
        ...
    }
}

控制台项目

namespace DataContractSerializerPOC
{
    class Program
    {
        static void Main(string[] args)
        {
            var personService = new PersonService();
            var people = personService.GetPeople();

            var memoryStream = new MemoryStream();
            var serializer = new DataContractSerializer(typeof(List<Person>));
            serializer.WriteObject(memoryStream, people);

            memoryStream.Seek(0, SeekOrigin.Begin);
            var text = new StreamReader(memoryStream).ReadToEnd();
        }
    }
}

结果

生成的 XML

因此 DataContractSerializer 能够使用私有 setter 处理属性,而 XmlSerializer 则不能。


推荐阅读