VS2019 发布和调用 WebService,以及 IIS 的坑
2023 年 7 月 4 日 · 5 分钟读完
目录
对接工厂 MES 时发现 WebService 挺有意思,记录一下创建、发布和调用的过程,以及遇到的问题。原来的三篇(发布调用、IIS 安装、403.14)合在这里。
WebService 是什么
WebService 是基于 HTTP 和 XML(SOAP 协议)的远程调用方式:服务端把方法公开出来,客户端像调本地方法一样调用,参数和返回值被打包成 XML 在网络上传输。服务会提供一份 WSDL 描述文件,说明有哪些方法、参数是什么类型,客户端根据它自动生成调用代码。
它的好处是跨平台、跨语言:Java 写的 MES 和 C# 写的上位机都认 SOAP。很多工厂的 MES、WMS 系统是十几年前建的,对外接口就是 WebService,所以上位机经常要对接它。
新项目一般用 REST 风格的 HTTP + JSON(见 WinForm 里的简单 HTTP 服务器与客户端),更轻量。
一、创建服务
- 新建「ASP.NET Web 应用程序(.NET Framework)」项目:

如果找不到这个模板,拉到列表最下方点「安装多个工具和功能」:

在 Visual Studio Installer 里勾选 ASP.NET 和 Web 开发:

装好后继续新建,模板选「空」:

- 项目右键 → 添加 → 新建项 → Web 服务(ASMX):

- 在生成的
WebService1类里加一个自己的方法。加了[WebMethod]特性的方法才会对外公开:

[WebMethod]
public string SendName(string name)
{
return "Hello " + name;
}
- F5 启动,浏览器会打开
WebService1.asmx,列出所有方法:

点方法名进入测试页,比如 SendName:

填参数、点「调用」,弹出返回的 XML:

服务创建完毕。地址后面加 ?wsdl 能看到 WSDL。
二、发布到 IIS
- 项目右键 → 发布,目标选「文件夹」:

可以在设置里勾选「发布前删除所有现有文件」,避免旧文件残留引起奇怪的问题:

- 打开计算机管理(或者直接搜「IIS」),找到 Internet Information Services (IIS) 管理器。没有的话见下文「系统里没有 IIS 管理器」:

- 右键「网站」→ 添加网站,物理路径选刚才发布的文件夹,填一个没被占用的端口:

注意 IP 地址:可以选本机的局域网 IP,也可以填 127.0.0.1(只能本机访问)。选了一个本机并没有的 IP,浏览时会一直超时。

- 右键网站 → 管理网站 → 浏览,打开
WebService1.asmx,能看到方法列表,说明发布成功:

三、客户端调用
新建一个调用方的项目(这里是控制台程序),右键 → 添加 → 服务引用:

地址要填到 .asmx(比如 http://192.168.1.10:8081/WebService1.asmx),只填到网站根目录是找不到服务的。点「转到」,展开就能看到方法:

VS 会根据 WSDL 生成代理类,调用起来就像本地方法:
var client = new ServiceReference1.WebService1SoapClient();
Console.WriteLine(client.SendName("wwww"));

代理类在添加服务引用时填的命名空间下,默认叫 ServiceReference1,添加时可以改成有意义的名字:

控制台打印出 SendName 的返回值,调用成功。
服务地址写在 app.config 的 <endpoint address="..."> 里,现场换服务器时改配置文件就行,不用重新编译。也可以在代码里指定:
// 第一个参数是 app.config 里 endpoint 的 name
var client = new ServiceReference1.WebService1SoapClient("WebService1Soap", "http://10.0.0.5:8081/WebService1.asmx");
客户端也有异步版本 SendNameAsync,在界面程序里用它不会卡界面。
四、问题汇总
系统里没有 IIS 管理器
Windows 默认没装 IIS,要手动打开:
- 控制面板 → 程序:

- 启用或关闭 Windows 功能:

- 勾选 Internet Information Services 下的「Web 管理工具」,以及「万维网服务 → 应用程序开发功能」里的 ASP.NET 4.x(只勾管理工具的话,网站能建但跑不了 ASP.NET):

Windows 会下载安装,可能要等一阵,直到提示「Windows 已完成请求的更改」:

- 在开始菜单搜「IIS」,能打开管理器就好了:

HTTP 错误 403.14 - Forbidden
「Web 服务器被配置为不列出此目录的内容」:访问的是网站根目录,而目录里没有默认文档(比如 index.html),IIS 又不允许列目录。

WebService 的情况下,正确的做法是访问具体的 .asmx 地址,而不是根目录。如果确实想看目录列表,有两种办法:
在网站的 web.config 里打开目录浏览:
<system.webServer>
<directoryBrowse enabled="true" />
</system.webServer>

或者在 IIS 管理器里选中网站 → 目录浏览 → 启用:

也可以在「默认文档」里把 WebService1.asmx 加进去,这样访问根目录就直接打开服务页。
另一个常见原因是 ASP.NET 没有注册到 IIS。这种情况访问 .asmx 会报 404 或 500,按上面勾选 ASP.NET 4.x 即可;老系统可以执行
aspnet_regiis -i。
浏览器提示「你的连接不是专用连接」
用 HTTPS 访问自己发布的服务、证书不受信任时会出现,见 浏览器提示「你的连接不是专用连接」。
HTTP 错误 404.3 - Not Found

文件明明在,却报 404.3,意思是 IIS 不知道怎么处理 .asmx 这种扩展名。原因是没有安装 ASP.NET 相关的 IIS 功能:在「启用或关闭 Windows 功能」里,勾选 Internet Information Services → 万维网服务 → 应用程序开发功能 → ASP.NET 4.x,以及 .NET Framework 4.x 高级服务 → WCF 服务 → HTTP 激活。参考:IIS 404.3 的解决办法。
「应用程序中的服务器错误」

这是 ASP.NET 的通用错误页,具体原因看页面上的错误信息。常见的有:应用程序池的 .NET CLR 版本不是 v4.0、web.config 里有当前 IIS 不支持的配置、发布的文件夹权限不够。参考:服务器错误的排查。
测试页「只能用于来自本地计算机的请求」
在别的电脑上打开 .asmx 页面,点进方法后没有「调用」按钮。这是默认的安全设置,只影响浏览器测试页,不影响客户端程序调用。确实需要远程测试时,在 web.config 里加:
<system.web>
<webServices>
<protocols>
<add name="HttpGet" />
<add name="HttpPost" />
</protocols>
</webServices>
</system.web>
别的电脑访问不了
依次检查:服务器上用 localhost 能不能打开;Windows 防火墙是否放行了网站端口;IIS 网站的绑定是不是只绑定了某个 IP。
延伸
- WebService 和 WCF:WCF 是微软后来的统一通讯框架,也支持 SOAP,ASMX 算是它的前辈。两者在 .NET Core 以后服务端都不再支持(社区有 CoreWCF),新项目服务端建议用 ASP.NET Core Web API。
- .NET Core / .NET 6 的客户端:没有「添加服务引用」的老界面,用「连接的服务」→ WCF Web Service,或者命令行工具
dotnet-svcutil生成代理,调用方式一样。 - 不想生成代理:SOAP 本质是 POST 一段 XML,可以用
HttpClient直接发,Content-Type: text/xml,请求体格式照着 .asmx 测试页上给的示例写。调试对接问题时这样最直观。 - XML 的转义:参数里有
<、&时要转义,见 JSON 与 XML 速查。
原文首发于 blog.csdn.net