代码之家  ›  专栏  ›  技术社区  ›  Eve

Web api-xml前缀

  •  0
  • Eve  · 技术社区  · 7 年前

      <test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:ai="www.something.org">
        <ai:name>Ann</name>
        </test>
    

    [XmlRoot(ElementName = "test")]
        public class Test
        {
            [XmlAttribute(AttributeName = "ai")]
            public const string Ai = "www.something.org";
            [XmlElement(ElementName = "name",Namespace = Ai)]
            public string Name { get; set; }
    
            public Test(string name)
            {
                Name = name;
            }
            public Test() { }
        }
    

    问题是,如果您单独使用xmlSerializer,您可以使用

    XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
    ns.Add("ai", "www.something.org");
    

    但在这里,序列化是由web api请求本身进行的:

    [HttpGet]
    [Route("test")]
    public Test Testing()
    {
     return new Test("Ann");
    }
    

    ai 属性,并且名称空间没有前缀。

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <name xmlns="www.something.org">
        Ann
        </name>
    

    如果我越过 XmlMediaTypeFormatter ,我得到了正确的xml响应:

    public class CustomXmlFormatter : XmlMediaTypeFormatter
        {
            public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content,
                TransportContext transportContext)
            {
                var serializer = new XmlSerializer(type);
                XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
                ns.Add("ai", "www.something.org");
    
                return Task.Factory.StartNew(() =>
                {
                    using (var streamWriter = new StreamWriter(writeStream, Encoding.UTF8))
                    {
                        serializer.Serialize(streamWriter, value,ns);
                    }
                });
                return base.WriteToStreamAsync(type, value, writeStream, content, transportContext);
            }
        }
    

    但是 如果我有两个请求,每个请求都有不同的名称空间,但这个格式化程序将始终显示这两个请求。有没有办法删除未使用的命名空间?

    1 回复  |  直到 7 年前
        1
  •  4
  •   peco    7 年前

    如果您这样定义自定义xml格式化程序:

    public class CustomXmlFormatter : XmlMediaTypeFormatter
    {
        public XmlSerializerNamespaces Namespaces { get; }
    
        public CustomXmlFormatter()
        {
            Namespaces = new XmlSerializerNamespaces();
        }
    
        public override Task WriteToStreamAsync(Type type, object value, System.IO.Stream writeStream, HttpContent content, TransportContext transportContext)
        {
            var serializer = new XmlSerializer(type);
    
            var xmlWriter = new XmlTextWriter(writeStream, Encoding.UTF8)
            {
                Namespaces = true
            };
    
            serializer.Serialize(xmlWriter, value, Namespaces);
    
            return Task.FromResult(true);
        }
    }
    

    然后您可以创建一个 IControllerConfiguration 使用此格式化程序并添加命名空间的:

    public class MyControllerConfig : Attribute, IControllerConfiguration
    {
        private readonly string _prefix;
        private readonly string _ns;
    
        public MyControllerConfig(string prefix, string ns)
        {
            _prefix = prefix;
            _ns = ns;
        }
    
        public void Initialize(HttpControllerSettings controllerSettings,
                                HttpControllerDescriptor controllerDescriptor)
        {
            var formatter = new CustomXmlFormatter { UseXmlSerializer = true };
            formatter.Namespaces.Add(_prefix, _ns);
            controllerSettings.Formatters.Clear();
            controllerSettings.Formatters.Add(formatter);
        }
    }
    

    [MyControllerConfig("ai", Ns.Ai)]
    public class MyController : ApiController
    {
        [HttpGet]
        [Route("test")]
        public IHttpActionResult Testing()
        {
            return Ok(new Test("Ann"));
        }
    }
    
    public class Ns
    {
        public const string Ai = "www.something.org";
    }
    
    [XmlRoot(ElementName = "test")]
    public class Test
    {
        [XmlElement(ElementName = "name", Namespace = Ns.Ai)]
        public string Name { get; set; }
    
        public Test(string name)
        {
            Name = name;
        }
        public Test() { }
    }