C# .NET 5异步Web API使用XPath读取XML节点遍历异常求助
问题排查与解决方案
核心问题原因
- XPath查询语法错误:XML中
CATEGORYID的属性值为字符串类型"10",原代码中//ITEM[@CATEGORYID=10]直接和数字10做对比,XML解析器会因类型不匹配查询不到节点,需要给属性值包裹单引号。 - 泛型集合类型不匹配:方法返回值声明为
List<InsertClassDTO>,但实例化时写的是new List<AnnuncioAutoDTO>(),若二者无继承关系,代码直接编译失败,无法进入执行阶段。 - 异步场景不符合需求:原代码全为同步写法,会阻塞Web API响应返回,无法实现先返回"ok"再处理业务的逻辑。
修复后代码示例
XML读取逻辑(适配异步场景)
public class LetturaXml { public async Task<List<InsertClassDTO>> XmlToListAsync(InputDTO input) { List<InsertClassDTO> list = new List<InsertClassDTO>(); // 用XDocument代替XmlDocument,API更友好且原生支持异步加载 XDocument doc = await XDocument.LoadAsync( File.OpenRead(input.filePath), LoadOptions.None, CancellationToken.None); // 修复XPath语法,给属性值加单引号 var nodeList = doc.XPathSelectElements("//ITEM[@CATEGORYID='10']"); foreach (var item in nodeList) { // 读取节点属性示例 var itemId = item.Attribute("ID")?.Value; // 读取普通子节点示例 var title = item.Element("TITLE")?.Value; // 读取属性列表中的指定值示例 var prezzo = item.Descendants("ATTRIBUTE") .FirstOrDefault(a => a.Element("ATTRID")?.Value == "prezzo")? .Element("ATTRVAL")?.Value; // 映射到DTO加入列表 list.Add(new InsertClassDTO { Id = itemId, Title = title, Prezzo = decimal.TryParse(prezzo, out var p) ? p : 0, // 其他字段按需求赋值 }); } // 后续批量插库建议用EF Core的AddRange+SaveChangesAsync,减少数据库交互次数 return list; } }
Web API层先返回响应的实现
[ApiController] [Route("api/[controller]")] public class XmlProcessController : ControllerBase { private readonly LetturaXml _letturaXml; private readonly ILogger<XmlProcessController> _logger; public XmlProcessController(LetturaXml letturaXml, ILogger<XmlProcessController> logger) { _letturaXml = letturaXml; _logger = logger; } [HttpPost] public IActionResult ProcessXml([FromBody] InputDTO input) { // 先做基础参数校验 if (!System.IO.File.Exists(input.filePath)) { return BadRequest("目标XML文件不存在"); } // 后台启动任务处理XML和插库逻辑,不阻塞响应返回 _ = Task.Run(async () => { try { await _letturaXml.XmlToListAsync(input); } catch (Exception ex) { // 必须添加异常日志,避免后台任务出错无感知 _logger.LogError(ex, "XML解析入库流程执行失败"); } }); return Ok("ok"); } }
生产环境注意事项
如果业务对任务执行可靠性要求高,后台长期运行的任务更推荐用IHostedService或者专业的任务调度组件,避免应用池回收导致未完成的任务中断。
内容的提问来源于stack exchange,提问作者galidan
相关产品推荐
相关产品推荐

