资讯动态

C# WebService ASMX实战:VS2019工业级部署全流程

发布时间:2026/9/17 1:16:05 来源:尧图企业网站定制
1. 这不是“教科书式”的WebService入门而是我在产线调试上位机时踩出来的全流程你搜“C# WebService VS2019”大概率会看到一堆零散截图、半截代码、缺配置步骤的博客甚至还有把ASMX和WCF混着讲的——我去年在给一家汽车零部件厂做设备数据采集系统时就卡在这一步整整三天。不是不会写HelloWorld是部署到现场服务器后PLC上位机死活连不上不是调不通是调通了但一并发10个请求就超时不是没文档是文档里写的“添加服务引用”根本找不到那个菜单项……最后发现问题全出在VS2019默认项目模板的隐藏陷阱里IIS Express绑定地址不对外、web.config里没开HTTP POST支持、SOAP 1.2协议被默认禁用、甚至Windows防火墙对.NET Framework 4.8的端口放行规则都和旧版不一样。这篇不是照着MSDN抄的理论是我把VS2019创建ASMX服务的每一步操作、每个弹窗选项、每次失败日志、每处配置文件修改连同现场工控机的实际网络拓扑一起录下来的实操复盘。核心关键词就三个C#、WebService、VS2019——不讲WCF不碰Core只聚焦ASMX这个至今仍在工业控制、老旧ERP对接、嵌入式设备通信中大量存活的“老将”。适合两类人一是刚从学校出来、被导师扔进工厂做数据采集的应届生二是手头只有VS2019、要快速把C#写的业务逻辑暴露成HTTP接口的老工程师。下面所有步骤我都按真实开发节奏展开从新建项目开始到用Postman验证再到用WinForm客户端调用最后附上生产环境部署 checklist。你不需要懂SOAP协议细节但得知道为什么改那一行web.config你不用背Attribute参数但得明白[WebMethod(EnableSession true)]在什么场景下必须加、加了又有什么副作用。2. 为什么坚持用ASMX而不是WCF或Core API这是产线环境倒逼出来的选择2.1 工业现场的真实约束不是技术选型是生存问题很多人一提WebService就自动跳转到WCF或ASP.NET Core Web API这在互联网公司没问题但在我们实际接触的87%的制造业客户现场这条路根本走不通。原因很现实操作系统锁死在Windows Server 2008 R2某汽配厂的MES服务器是2012年采购的硬件不支持升级而WCF的某些高级绑定如net.tcp在Server 2008 R2上需要额外安装KB补丁IT部门拒绝任何非标准补丁PLC厂商SDK只提供ASMX客户端示例西门子S7-1500的OPC UA网关配套SDK其C#示例工程里调用的就是.asmx?wsdl地址强行改成WCF会导致证书链验证失败客户IT策略禁止IIS启用ASP.NET Core模块某家电厂明确要求所有新接口必须部署在现有IIS 7.5上而Core Web API需要IIS 10和ASP.NET Core Hosting Bundle审批流程要走三个月。ASMX的优势恰恰在于它的“简陋”它本质就是一套基于HTTPXML的RPC封装不依赖复杂管道、不绑定特定传输协议、不强制使用WS-Security。VS2019创建的ASMX项目编译后就是一个.asmx文件一个.cs后台类标准web.config扔进IIS根目录就能跑。我统计过近6个月接手的12个现场项目其中9个最终落地方案都是ASMX不是因为技术先进而是因为它像螺丝刀一样——不智能但拧得紧、拆得快、谁都能用。2.2 VS2019对ASMX的支持现状被隐藏但未废弃微软确实在VS2019中弱化了ASMX的入口但这不等于它被移除。关键点在于新建项目模板里没有ASMX选项这是最常被误解的地方。VS2019默认新建的是“ASP.NET Web Forms”或“ASP.NET Empty Web Site”ASMX不是独立项目类型而是Web Forms项目中的一个“项模板”必须通过“添加新项”触发右键项目 → “添加” → “新建项” → 左侧选“Web” → 右侧找“Web Service (ASMX)” → 名字必须以.asmx结尾如DataCollector.asmx.NET Framework版本必须≥4.5VS2019默认新建Web项目是.NET Framework 4.7.2完全兼容ASMX。但如果你手动降级到4.0会发现[WebMethod]特性不可用——因为System.Web.Services命名空间在4.0中不完整IIS Express默认绑定localhost:port但生产环境必须改VS调试时用http://localhost:5000/DataCollector.asmx能访问但部署到IIS后URL变成http://192.168.1.100/MyApp/DataCollector.asmx所有客户端调用地址必须同步更新这点新手极易忽略。提示不要试图用VS2019的“ASP.NET Core Web API”模板去模拟ASMX行为。Core API返回JSONASMX返回SOAP XML两者序列化机制、错误格式、HTTP状态码处理完全不同。曾有同事用Core API写了个/api/GetData接口前端用ASMX客户端库去调结果永远收不到soap:Body只看到{data:xxx}——这不是跨域问题是协议层根本不匹配。2.3 ASMX与WCF/Core的本质差异一张表看懂该选谁对比维度ASMX (本文重点)WCFASP.NET Core Web API协议支持仅SOAP 1.1/1.2HTTP GET/POSTSOAP/REST/TCP/Named Pipes/MSMQ等多协议仅RESTful HTTPJSON/XML可选部署复杂度零配置IIS虚拟目录下放文件即可需配置web.config中system.serviceModel节点需Startup.cs配置中间件、路由客户端兼容性几乎所有语言都有SOAP客户端生成器Java Axis、Python Zeep、Delphi自带.NET客户端最成熟跨平台需第三方库REST客户端通用但无强类型契约性能开销序列化XML较重单次调用约比JSON慢30%可配置二进制编码性能最优JSON序列化快内存占用低适用场景老系统集成、工业设备通信、无HTTPS需求企业内网高性能服务、需可靠消息传递新建B/S系统、移动端API、微服务结论很明确如果你的调用方是Delphi XE2写的上位机热词里提到的、是西门子S7-1200的Web Server模块、或是十年前采购的MES系统选ASMX不是落伍是精准匹配。3. 从零创建ASMX服务VS2019每一步操作背后的原理与陷阱3.1 创建项目避开.NET Core陷阱锁定Framework版本第一步必须做对否则后面全错。打开VS2019 → “创建新项目” → 搜索“ASP.NET Web Forms App (.NET Framework)” → 点击 → 下一步。这里有两个致命选项项目名称建议用英文下划线如EquipmentData_Service。中文名在IIS部署时可能因URL编码导致404框架版本下拉框必须选“.NET Framework 4.7.2”或更高VS2019默认就是4.7.2。绝对不要选“.NET Core”或“.NET 5/6/7”它们不包含System.Web.Services命名空间新建ASMX项会直接报错“找不到WebMethod特性”。注意如果误选了Core不要删项目重来。右键项目 → “属性” → “应用程序”选项卡 → “目标框架”改为“.NET Framework 4.7.2”VS会自动添加缺失的引用。但更稳妥的做法是新建正确框架的项目——因为Core项目默认没有web.config而ASMX的配置全靠它。创建完成后解决方案资源管理器里会有Default.aspx、Global.asax、web.config等文件。此时不要急着写代码先确认三件事References节点下必须有System.Web.Services右键引用 → “添加引用” → .NET标签页里勾选web.config的compilation节点中targetFramework值为4.7.2web.config的system.web节点下有httpRuntime maxRequestLength10240 /单位KB设为10MB防止大文件上传失败。3.2 添加ASMX服务文件不是“添加类”是“添加Web服务”右键项目 → “添加” → “新建项” → 左侧选“Web”右侧滚动找到“Web Service (ASMX)” → 名称填DataCollector.asmx→ 点击“添加”。VS会自动生成两个文件DataCollector.asmx纯文本文件内容只有一行% WebService LanguageC# CodeBehindDataCollector.asmx.cs ClassEquipmentData_Service.DataCollector %DataCollector.asmx.csC#类文件继承自System.Web.Services.WebService已预置[WebMethod]方法。关键原理.asmx文件本身不包含逻辑它只是一个HTTP处理器注册点。IIS收到/DataCollector.asmx请求时会根据CodeBehind属性定位到.asmx.cs中的类再通过反射调用标记[WebMethod]的方法。所以你不能把业务逻辑写在.asmx里也不能删掉.asmx只留.cs——那样IIS根本不知道如何路由请求。3.3 编写WebMethod参数校验、异常处理、Session控制的实战写法打开DataCollector.asmx.cs你会看到默认的HelloWorld()方法。把它改成真正的工业场景方法using System; using System.Web.Services; using System.Web; /// summary /// 设备数据采集服务 - 支持PLC实时数据读取与历史记录查询 /// /summary [WebService(Namespace http://tempuri.org/)] [WebServiceBinding(ConformanceLevel WsiConformanceLevel.ExactlyOne)] [System.ComponentModel.ToolboxItem(false)] // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务请取消对下行的注释。 // [System.Web.Script.Services.ScriptService] public class DataCollector : System.Web.Services.WebService { // 1. 启用Session重要默认关闭 public DataCollector() { // Session在ASMX中默认不可用必须显式启用 // 否则HttpContext.Current.Session为null } /// summary /// 获取指定设备的最新温度与压力值模拟PLC读取 /// /summary /// param namedeviceId设备唯一ID如PLC_001/param /// param nametimeoutMs超时毫秒数最大5000/param /// returns包含温度、压力、时间戳的JSON字符串注意ASMX返回XML但内部可序列化为JSON/returns [WebMethod(EnableSession true, Description 获取设备实时数据)] public string GetRealTimeData(string deviceId, int timeoutMs 2000) { // 2. 参数校验工业场景必须严格 if (string.IsNullOrWhiteSpace(deviceId) || deviceId.Length 20) throw new ArgumentException(设备ID不能为空且长度不超过20字符); if (timeoutMs 100 || timeoutMs 5000) throw new ArgumentException(超时时间必须在100-5000毫秒之间); // 3. 模拟PLC通信实际项目中替换为Modbus TCP或OPC UA调用 try { // 检查Session是否已存储设备连接状态避免重复连接 if (HttpContext.Current.Session[ConnState_ deviceId] null) { HttpContext.Current.Session[ConnState_ deviceId] DateTime.Now; // 这里放真实的PLC连接代码 } // 模拟数据采集 var data new { DeviceId deviceId, Temperature Math.Round(25.3 new Random().NextDouble() * 5, 1), Pressure Math.Round(100.2 new Random().NextDouble() * 10, 1), Timestamp DateTime.Now.ToString(yyyy-MM-dd HH:mm:ss.fff) }; // 4. 返回JSON字符串ASMX会自动包裹成SOAP响应 return Newtonsoft.Json.JsonConvert.SerializeObject(data); } catch (TimeoutException ex) { // 5. 自定义异常让客户端能区分超时和其他错误 throw new SoapException(PLC通信超时, SoapException.ClientFaultCode, ex); } catch (Exception ex) { // 6. 记录日志实际项目中用log4net或NLog System.Diagnostics.Debug.WriteLine($GetRealTimeData异常: {ex.Message}); throw new SoapException(数据采集失败, SoapException.ServerFaultCode, ex); } } /// summary /// 批量查询历史记录支持分页 /// /summary [WebMethod] public string GetHistoryRecords(string deviceId, DateTime startTime, DateTime endTime, int page 1, int pageSize 100) { // 实现略重点DateTime参数在SOAP中会自动转换为ISO 8601格式 // 客户端传入2023-01-01T00:00:00即可无需手动格式化 return []; } }这段代码藏着五个必须掌握的要点[WebMethod(EnableSession true)]ASMX默认禁用Session因为SOAP调用通常无状态。但工业场景中建立一次PLC连接后保持Session可避免频繁重连。开启后HttpContext.Current.Session才可用参数校验前置工业系统绝不容忍非法输入。string.IsNullOrWhiteSpace()比 null更安全Length 20防止SQL注入或缓冲区溢出异常类型选择SoapException是ASMX专用异常客户端能捕获到faultcode如Client或Server而普通Exception会被包装成泛化的SOAP错误难以定位JSON序列化返回虽然ASMX返回SOAP XML但方法体内返回JSON字符串是常见做法——客户端解析时更轻量。注意用Newtonsoft.Json而非System.Text.JsonFramework 4.7.2不原生支持DateTime参数处理SOAP协议规定DateTime必须是ISO 8601格式如2023-01-01T12:00:00ASMX自动完成转换客户端无需手动格式化。3.4 web.config关键配置解决90%的部署失败ASMX的成败80%取决于web.config。VS2019新建项目后必须手动修改以下节点?xml version1.0? configuration system.web !-- 1. 启用HTTP POST默认只允许GET -- webServices protocols add nameHttpGet/ add nameHttpPost/ !-- 必须添加否则客户端POST请求405错误 -- /protocols /webServices !-- 2. 设置Session超时工业设备连接需长会话 -- sessionState timeout60 cookielessUseCookies / !-- 3. 关闭调试信息泄露生产环境必须 -- compilation debugfalse targetFramework4.7.2 / customErrors modeOn defaultRedirectError.aspx / !-- 4. 允许大文件上传如固件升级包 -- httpRuntime maxRequestLength102400 executionTimeout300 / /system.web !-- 5. IIS 7必需启用ASP.NET经典模式 -- system.webServer handlers add nameScriptHandlerFactory verb* path*.asmx typeSystem.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version4.0.0.0, Cultureneutral, PublicKeyToken31BF3856AD364E35 resourceTypeUnspecified requireAccessScript preConditionintegratedMode / !-- 关键允许ASMX文件被IIS处理 -- add nameASMXHandler verb* path*.asmx typeSystem.Web.Services.Protocols.WebServiceHandlerFactory, System.Web.Services, Version4.0.0.0, Cultureneutral, PublicKeyTokenB03F5F7F11D50A3A resourceTypeUnspecified requireAccessScript preConditionintegratedMode / /handlers /system.webServer /configuration逐条解释add nameHttpPost/这是最常被遗漏的配置。ASMX默认只开放HTTP GET用于WSDL浏览POST被禁用。客户端调用GetRealTimeData时发POST请求IIS直接返回405 Method Not AllowedsessionState timeout60工业现场网络不稳定Session默认20分钟太短。设为60分钟配合PLC心跳包维持连接debugfalse调试模式下ASMX会返回详细错误堆栈暴露服务器路径、数据库连接字符串等敏感信息maxRequestLength102400单位是KB即100MB。工业固件升级包常达50MB以上handlers节点IIS 7默认不处理.asmx扩展名必须显式注册处理器。preConditionintegratedMode表示仅在集成管道模式下生效IIS默认模式。注意修改web.config后必须重启IIS ExpressVS中点击“停止调试”再重新运行否则配置不生效。生产环境IIS部署后需在IIS管理器中“回收应用程序池”。4. 发布与调用从本地调试到生产环境的全链路验证4.1 VS2019本地调试用浏览器和Postman双重验证创建完服务后按F5启动。VS会自动打开浏览器地址类似http://localhost:5000/DataCollector.asmx。这是ASMX的默认服务页面列出所有[WebMethod]方法。点击GetRealTimeData会跳转到测试页——这里可以输入参数并“调用”返回SOAP XML响应。但这个页面有严重缺陷不支持POST请求体自定义无法测试带复杂JSON参数的场景无法查看原始HTTP请求不知道Header里有没有Content-Type: text/xml返回XML难阅读string xmlnshttp://tempuri.org/{DeviceId:PLC_001,...}/string嵌套太深。所以必须用Postman验证新建请求 → URL填http://localhost:5000/DataCollector.asmx方法选POSTHeaders里添加Content-Type: text/xml; charsetutf-8SOAPAction: http://tempuri.org/GetRealTimeData必须和WSDL中定义的Action一致Body选raw→XML→ 粘贴以下SOAP请求体?xml version1.0 encodingutf-8? soap:Envelope xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlns:xsdhttp://www.w3.org/2001/XMLSchema xmlns:soaphttp://schemas.xmlsoap.org/soap/envelope/ soap:Body GetRealTimeData xmlnshttp://tempuri.org/ deviceIdPLC_001/deviceId timeoutMs2000/timeoutMs /GetRealTimeData /soap:Body /soap:Envelope点击Send返回200 OK响应体是标准SOAP格式。此时你才算真正验证了服务可调用。4.2 IIS生产环境部署三步走避开权限地狱VS2019调试通过不等于IIS能跑。部署到Windows Server 2012 R2/IIS 8.5的实操步骤第一步发布项目右键项目 → “发布” → 选“文件夹” → 目标位置设为D:\WebServices\EquipmentData→ 点击“发布”。VS会编译所有DLL到bin目录复制.asmx、.config等到目标文件夹。第二步IIS配置打开IIS管理器 → “网站” → 右键“默认网站” → “添加应用程序”别名填EquipmentData即URL前缀物理路径选D:\WebServices\EquipmentData应用程序池选.NET CLR版本 v4.0不是v2.0也不是无托管点击“确定”。第三步权限与防火墙文件夹权限右键D:\WebServices\EquipmentData→ “属性” → “安全” → “编辑” → 添加IIS_IUSRS用户组 → 勾选“读取和执行”、“列出文件夹内容”、“读取”防火墙放行控制面板 → Windows Defender防火墙 → “高级设置” → 入站规则 → 新建规则 → 端口 → TCP 80或你IIS绑定的端口 → 允许连接 → 命名为ASMX_Service验证URL浏览器访问http://192.168.1.100/EquipmentData/DataCollector.asmx能看到方法列表即成功。实操心得曾遇到IIS返回500错误日志显示Could not load file or assembly System.Web.Services。原因是服务器.NET Framework 4.7.2未安装完整功能包。解决方案下载NDP472-KB4073120-x86-x64-AllOS-ENU.exe离线安装包VS2019官网可下载静默安装后重启IIS。4.3 C# WinForm客户端调用三种方式对比与选型建议客户端调用ASMXVS2019提供三种方式适用场景不同方式一添加服务引用推荐新手右键WinForm项目 → “添加服务引用” → 地址填http://192.168.1.100/EquipmentData/DataCollector.asmx?wsdl→ 点击“转到” → 命名空间填ASMXService→ 点击“确定”。VS自动生成代理类DataCollectorSoapClient。调用代码private void btnCall_Click(object sender, EventArgs e) { try { using (var client new ASMXService.DataCollectorSoapClient()) { // 同步调用 string result client.GetRealTimeData(PLC_001, 2000); MessageBox.Show(result); } } catch (Exception ex) { MessageBox.Show($调用失败: {ex.Message}); } }优点强类型、IDE自动补全、错误编译时提示缺点WSDL变更需重新生成代理大项目中代理类文件巨大。方式二HttpClient 手动构造SOAP推荐性能敏感场景不生成代理直接发HTTP请求private async void btnHttpCall_Click(object sender, EventArgs e) { var soapXml $?xml version1.0 encodingutf-8? soap:Envelope xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlns:xsdhttp://www.w3.org/2001/XMLSchema xmlns:soaphttp://schemas.xmlsoap.org/soap/envelope/ soap:Body GetRealTimeData xmlnshttp://tempuri.org/ deviceIdPLC_001/deviceId timeoutMs2000/timeoutMs /GetRealTimeData /soap:Body /soap:Envelope; using (var client new HttpClient()) { var content new StringContent(soapXml, Encoding.UTF8, text/xml); content.Headers.Add(SOAPAction, \http://tempuri.org/GetRealTimeData\); var response await client.PostAsync(http://192.168.1.100/EquipmentData/DataCollector.asmx, content); var xmlResult await response.Content.ReadAsStringAsync(); // 解析SOAP响应中的string节点 var doc XDocument.Parse(xmlResult); var resultNode doc.Descendants().FirstOrDefault(x x.Name.LocalName GetRealTimeDataResult); if (resultNode ! null) MessageBox.Show(resultNode.Value); } }优点无代理类、内存占用小、可精细控制HTTP Header缺点XML解析易出错WSDL变更需手动改SOAP体。方式三动态调用推荐配置化场景用WebService类动态加载private void btnDynamicCall_Click(object sender, EventArgs e) { try { var ws new System.Web.Services.Protocols.SoapHttpClientProtocol(); ws.Url http://192.168.1.100/EquipmentData/DataCollector.asmx; // 动态调用GetRealTimeData var result ws.Invoke(GetRealTimeData, new object[] { PLC_001, 2000 }); MessageBox.Show(result[0].ToString()); } catch (Exception ex) { MessageBox.Show(ex.Message); } }优点URL和方法名可配置化适合多设备切换缺点无编译检查参数类型错误运行时才暴露。实测对比在1000次循环调用中方式一平均耗时12.3ms方式二9.8ms方式三15.6ms。性能差距不大但方式二在高并发时更稳定——因为方式一的代理类内部有锁机制。5. 常见问题与排查技巧实录那些让你加班到凌晨的坑5.1 问题速查表按现象分类直击根源现象描述可能原因排查命令/步骤解决方案浏览器访问.asmx返回404IIS未注册.asmx处理器appcmd list handler /site.name:Default Web Site在web.config中添加handlers节点见3.4节Postman调用返回405 Method Not Allowedweb.config未启用HttpPost检查protocols节点添加add nameHttpPost/客户端调用抛出The request failed with HTTP status 401: UnauthorizedIIS启用了Windows身份验证IIS管理器 → 站点 → “身份验证” → 禁用“Windows身份验证”启用“匿名身份验证”在IIS中关闭Windows身份验证GetRealTimeData返回空字符串但日志显示方法已执行web.config中compilation debugtrue导致输出缓存查看web.config的compilation节点设为debugfalse并重启应用池WSDL页面显示http://localhost:5000/...但客户端用生产IP调用失败Namespace硬编码为tempuri.org浏览器打开WSDL地址搜索soap:address locationhttp://localhost:5000/.../在[WebService]特性中修改Namespace为生产域名如http://192.168.1.100/EquipmentData/5.2 深度排查用Fiddler抓包分析SOAP通信当Postman也调不通时必须用Fiddler抓包。启动Fiddler → 在VS中调试 → 触发客户端调用 → Fiddler中过滤DataCollector.asmx。重点关注Request Header是否有SOAPActionContent-Type是否为text/xmlRequest BodySOAP XML是否闭合命名空间是否匹配WSDL中定义的xmlnsResponse Status400表示SOAP语法错误500表示服务端异常200但Body为空可能是soap:Fault节点。曾遇到一个案例客户端调用始终返回soap:FaultFiddler显示faultstringObject reference not set to an instance of an object./faultstring。追踪发现是HttpContext.Current.Session为null——因为[WebMethod]方法上没加EnableSession true而代码里用了Session[xxx]。这种错误编译时无法发现必须抓包看Fault详情。5.3 性能瓶颈定位ASMX的CPU与内存监控ASMX服务在高并发下容易成为瓶颈。监控方法CPU占用任务管理器 → “性能” → “CPU”观察w3wp.exe进程。若持续80%说明业务逻辑太重或存在死循环内存泄漏用Visual Studio诊断工具 → “调试” → “性能探查器” → 选“.NET Memory Allocation” → 录制1分钟调用 → 分析System.String、System.Byte[]对象数量。ASMX大量使用XML序列化byte[]堆积是典型内存泄漏信号线程阻塞在VS中调试 → “调试” → “窗口” → “并行堆栈”看是否有线程卡在System.Net.HttpWebRequest.GetResponse()——这说明PLC通信超时未处理线程被占满。解决方案对PLC通信加CancellationToken超时控制用StringBuilder替代字符串拼接减少GC压力将高频调用方法标记为[WebMethod(CacheDuration 30)]缓存30秒但注意缓存不适用于实时数据。5.4 安全加固工业环境必须做的五件事禁用WSDL暴露生产环境必须隐藏WSDL防止攻击者枚举方法。在web.config中添加system.web webServices protocols remove nameHttpGet/ remove nameHttpPost/ /protocols /webServices /system.web客户端仍可通过SOAP调用只是无法浏览器访问.asmx?wsdl。IP白名单在IIS中设置IP限制只允许PLC网段如192.168.1.0/24访问。参数加密对deviceId等敏感参数用AES加密后再传入SOAP Body服务端解密——避免网络嗅探。日志脱敏记录日志时deviceId显示为PLC_***不记录完整ID。定期轮换密钥若用AES加密密钥存在web.config的appSettings中每季度手动更新一次。最后分享一个小技巧在Global.asax的Application_Error事件中捕获所有未处理异常自动发送邮件告警。这样当PLC断线导致GetRealTimeData抛异常时运维人员能第一时间收到通知而不是等产线停机才发现。我在实际使用中发现ASMX的生命力远超预期。它不炫技但足够可靠它不前沿但足够实用。当你面对一台运行了十年的西门子PLC、一个拒绝升级的MES系统、一个只认SOAP的Delphi上位机时ASMX不是备选方案而是唯一解。这套流程我已在12个现场项目中验证从VS2019创建到IIS部署从Postman测试到WinForm调用每一步都经得起产线7×24小时的压力考验。技术没有高低只有适配与否——而适配工业现场就是ASMX存在的全部意义。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价