提交XML至服务器Web Service遇'an'意外令牌错误求助
遇到这种本地调试正常、部署到服务器就报错的问题确实头疼——我帮你一步步拆解排查:
先定位错误核心
从错误栈能看到,问题出在XmlDocument.LoadXml(orderXml)这一行,说明服务器接收到的orderXml字符串不是合法的XML结构。本地调试正常,大概率是服务器环境下接收到的XML内容和本地不一致,或是服务器端的环境差异导致的。
1. 先记录服务器实际收到的XML内容
你现在的代码把异常直接吞掉了,根本看不到出问题的XML到底是什么。先修改InsertSecure方法,添加日志记录,把收到的orderXml和异常信息保存下来:
[WebMethod(Description = "Use this web service to submit new work orders. This needs authentication")] [SoapHeader("User", Required = true)] public XmlDocument InsertSecure(string orderXml) { if (User != null && User.IsValid()) { try { // 记录收到的orderXml,方便排查差异 string logDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "WsLogs"); if (!Directory.Exists(logDir)) Directory.CreateDirectory(logDir); string orderLogPath = Path.Combine(logDir, $"OrderXml_{DateTime.Now:yyyyMMddHHmmss}.txt"); File.WriteAllText(orderLogPath, orderXml); XmlDocument xdoc = new XmlDocument(); xdoc.LoadXml(orderXml); return createXML(xdoc); } catch (Exception ex) { // 记录异常详情 string errorLogPath = Path.Combine(logDir, $"Error_{DateTime.Now:yyyyMMddHHmmss}.txt"); File.WriteAllText(errorLogPath, $"Exception: {ex.ToString()}\n\nReceived OrderXml:\n{orderXml}"); // 返回明确的错误信息,不要吞掉异常 XmlDocument xErrorDoc = new XmlDocument(); xErrorDoc.LoadXml($"<?xml version='1.0' encoding='utf-8' ?><DocumentElement><Error>{ex.Message}</Error></DocumentElement>"); return xErrorDoc; } } else { // 原未授权逻辑保留,格式稍微调整下 XmlDocument xAuthDeniedDoc = new XmlDocument(); xAuthDeniedDoc.LoadXml(@"<?xml version='1.0' encoding='utf-8' ?> <DocumentElement> <Response>Unauthorized Access</Response> </DocumentElement>"); return xAuthDeniedDoc; } }
部署后再提交请求,查看日志里的orderXml,对比本地调试时的内容,就能快速发现差异——比如是不是CDATA被转义了,或者某些字符被服务器的代理/IIS修改了。
2. 修正createXML方法的路径隐患
你的createXML方法里的路径拼接有问题,服务器环境下Directory.GetCurrentDirectory()返回的是IIS的工作目录,不是你的Web应用根目录,会导致文件保存失败(虽然这次错误不是这个导致的,但先修好避免后续坑):
private XmlDocument createXML(XmlDocument xdoc) { try { // 使用Web应用根目录拼接路径,更可靠 string webRoot = AppDomain.CurrentDomain.BaseDirectory; string saveDir = Path.Combine(webRoot, "WebServiceXML"); if (!Directory.Exists(saveDir)) { Directory.CreateDirectory(saveDir); } string timeStamp = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"); string fileName = $"WorksOrderXML-{timeStamp}.xml"; xdoc.Save(Path.Combine(saveDir, fileName)); // 构造成功响应 XmlDocument xSucessDoc = new XmlDocument(); xSucessDoc.LoadXml(@"<?xml version='1.0' encoding='utf-8' ?> <DocumentElement> <SuccessResponse>Order Received Successfully</SuccessResponse> </DocumentElement>"); return xSucessDoc; } catch(Exception ex) { // 记录异常并返回错误信息 string logDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "WsLogs"); if (!Directory.Exists(logDir)) Directory.CreateDirectory(logDir); File.WriteAllText(Path.Combine(logDir, $"CreateXmlError_{DateTime.Now:yyyyMMddHHmmss}.txt"), ex.ToString()); XmlDocument xErrorDoc = new XmlDocument(); xErrorDoc.LoadXml($"<?xml version='1.0' encoding='utf-8' ?><DocumentElement><Error>Failed to process order: {ex.Message}</Error></DocumentElement>"); return xErrorDoc; } }
3. 排查客户端SOAP请求的CDATA处理
如果日志显示服务器收到的orderXml不是完整的<Root><County>Dorset</County></Root>,而是被转义成了<Root><County>Dorset</County></Root>,那说明客户端提交时CDATA没有被正确解析:
- 确保客户端构造SOAP请求时,
<orderXml>里的内容确实被<![CDATA[...]]>完整包裹,没有被额外转义 - 如果用HttpClient/WebRequest提交,确保请求的
Content-Type是text/xml; charset=utf-8,不要让框架自动转义XML内容
4. 检查服务器配置与.NET版本
确认服务器上部署的.NET Framework版本和本地VS调试时的版本一致,不同版本的XML解析器可能有细微差异;另外检查IIS的请求筛选规则,有没有拦截或修改XML内容的设置。
总结
最可能的原因是服务器接收到的orderXml内容和本地不一致,通过日志记录就能快速定位问题。另外一定要改掉空catch块,吞掉异常会让排查变得无比困难。
内容的提问来源于stack exchange,提问作者kas_miyulu

