我应该在数据库中存储XML声明并使用WebApi返回

时间:2017-10-18 13:34:04

标签: sql-server xml asp.net-web-api encoding asp.net-core

情景:

用户使用WebApi提交XML,我想将其存储在XML列的SQL数据库中,稍后使用Ajax / WebApi检索

问题:

我应该如何将其存储在数据库中?有或没有声明/编码?或者我应该在返回XML时添加编码吗?

public async IActionResult Post([FromBody]XDocument xml)
{
   var entity = new MyDocument();
   entity.Xml = xml.ToString(); //?? 
   db.Documents.Add(entity);
   db.SaveChanges();
   return Created();
}

public async Task<IActionResult> Get(int id)
{
   var entity = db.Documents.Find(id);
   return Content(entity.Xml, "application/xml"); //missing xml declaration
}

我的观察:

  • XDocument.ToString()修剪XML声明元素:

    var xml = XDocument.Load(@"<?xml version=""1.0"" encoding=""utf-8""?>
                               <Root><Child>Content</Child></Root>");
    xml.ToString(); //<Root><Child>Content</Child></Root>
    

    包含它很容易,但我认为这可能是有原因的。

  • 当响应不包含xml声明时,Edge浏览器不显示XML:

    public IActionResult Get()
    {
        return Content("<Root><Child>Content</Child></Root>", "application/xml")
    }
    
  • 当响应包含xml声明,但声明中的编码与响应编码不匹配时,它也会失败并且&#34;无法切换编码&#34;:

    public IActionResult Get()
    {
        return Content(@"<?xml version=""1.0"" encoding=""utf-8""?>
                         <Root><Child>Content</Child></Root>", "application/xml");
    }
    
  • 为了让Edge浏览器正确显示XML,我必须做以下事情:

    public IActionResult Get()
    {
        string xml = @"<?xml version=""1.0"" encoding=""utf-8""?>
                       <Root><Child>Content</Child></Root>")
        var xmlDoc = XDocument.Parse(xml);
        return Content(xml, "application/xml", Encoding.GetEncoding(xmlDoc.Declaration.Encoding));
    }
    

由于数据库也有一些编码,对我来说很不清楚,实际上是什么方法。

1 个答案:

答案 0 :(得分:0)

我已将这些规则确定为最佳做法:

  1. 您不应将XML编码存储在数据库

    • 声明是可选的,但如果存在,则不得包含编码
  2. 您的WebApi应始终返回XML声明。

    • 编码是可选的,但如果存在,则必须匹配响应编码
  3. 说明:

    很明显,您不希望在数据库中存储编码,因为数据库威胁XML列。但是,将XML声明存储在数据库中是有意义的,因为它可以包含其他信息(版本,独立)。

    您的REST服务应始终在响应中返回XML声明。如果它没有存储在数据库中,您可以在运行时构建它。

    public async IActionResult Post([FromBody]XDocument xml)
    {
       var entity = new MyDocument();
       var declarationWithoutEncoding = new XDeclaration(xml.Declaration?.Version, null, xml.Declaration?.Standalone);
       entity.Xml = $@"{declarationWithoutEncoding}\n\r{xml.ToString()}"
       db.Documents.Add(entity);
       db.SaveChanges();
       return Created();
    }
    
    public async Task<IActionResult> Get(int id)
    {
       var entity = db.Documents.Find(id);
       return Content(entity.Xml, "application/xml"); //in case XML Declaration is in database
    }
    

    alternativelly

    public async Task<IActionResult> Get(int id)
    {
       var entity = db.Documents.Find(id);
       XDocument xmlDoc = XDocument.Parse(entity.xml);
    
       var declaration = new XDeclaration(xml.Declaration?.Version ?? "1.0", null, xml.Declaration?.Standalone ? "no");
    
       //you may change enccoding information to match response encoding, or just skip it
       //declaration.Encoding = ...
    
       string xml = $@"{declaration}\n\r{xml.ToString()}"
    
       return Content(xml, "application/xml"); 
    }