WCF / EF / SQL Server / VS2017 / C#:多层应用程序在部署到本地 IIS 10.0 作为托管服务器时出错
Posted
技术标签:
【中文标题】WCF / EF / SQL Server / VS2017 / C#:多层应用程序在部署到本地 IIS 10.0 作为托管服务器时出错【英文标题】:WCF / EF / SQL Server / VS2017 / C# : multi-tier application gets error when deployed to local IIS 10.0 as hosting server 【发布时间】:2020-09-12 18:42:19 【问题描述】:我正在尝试部署具有服务层、逻辑层和数据层的 Windows 桌面应用程序。数据层使用带有 EF 6.2 的 SQL Server。 UI 客户端层是一个 Windows 窗体应用程序。
当服务由 IIS 中的服务别名 WcfSvcUtil.exe
应用程序托管时,该应用程序在测试调试模式下运行良好 - 没有错误,所有数据检索和更新都在测试中工作。
现在,我已将服务层、逻辑层和数据层发布为一个空网站,由 IIS 托管在我的本地计算机 (c:/inetpub/wwwroot/) 的“alias”子文件夹中。我创建了一个以服务别名命名的 IIS 应用程序。 UI 层和 Service 层发布到我机器上的不同本地文件夹。
当我启动 UI 层并尝试查询 SQL Server 数据库时,我收到以下错误:
http://localhost/TheACTSFactoryWCFLocal/MemberService/ 上没有可以接受消息的端点监听。这通常是由不正确的地址或 SOAP 操作引起的。有关详细信息,请参阅 innerException(如果存在)。
托管网站web.config
中的我的服务模型元素是:
<system.serviceModel>
<services>
<service name="ACTSFactoryService.MemberService">
<endpoint name="BasicHttpBinding_IMemberService"
address=""
binding="basicHttpBinding"
contract="ACTSFactoryService.IMemberService" >
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost/TheACTSFactoryWCFLocal/MemberService/" />
</baseAddresses>
</host>
</service>
</services>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true">
<serviceActivations>
<add factory="System.ServiceModel.Activation.ServiceHostFactory"
relativeAddress="./MemberService.svc"
service="ACTSFactoryService.MemberService" />
</serviceActivations>
</serviceHostingEnvironment>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMemberService"
maxReceivedMessageSize="20000000" maxBufferSize="20000000" />
</basicHttpBinding>
</bindings>
</system.serviceModel>
我是 WCF 和实体框架的新手,所以任何建议都将不胜感激。我在服务层还有app.config
和web.config
,在UI 层还有app.config
。如果您认为它们会有所帮助,我可以发布它们,但是对于显示的 IIS web.config
,我基本上将服务层配置文件中的端点组合在一起以发布到 IIS 网站。
** 将我的 web.config 文件更改如下 **
***
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5.2" />
</system.web>
<system.serviceModel >
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" >
<serviceActivations >
<add factory ="System.ServiceModel.Activation.ServiceHostFactory"
relativeAddress="./MemberService.svc"
service="ACTSFactoryService.MemberService" />
</serviceActivations>
</serviceHostingEnvironment>
<behaviors >
<serviceBehaviors >
<behavior >
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
***
另外,当我浏览到http://localhost/TheACTSFactoryWCFLocal/MemberService.svc 时,我的服务被找到了。
UI层的App.config如下:
***
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMemberService" maxBufferSize="20000000"
maxReceivedMessageSize="20000000" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/TheACTSFactoryWCFLocal/MemberService/"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMemberService"
contract="MemberServiceProxy.IMemberService" />
</client>
</system.serviceModel>
</configuration>
***
这里是以 IIS 应用的别名命名的 IIS 服务器文件夹,没有 SVC 文件
这里是发布到 Bin 文件夹的 DLL 等
对于托管在 .NET 4.5.2 中的 IIS 10.0 中的 WCF 服务,IIS 服务器的 Alias/Bin 文件夹部署看起来是否正常?此外,我没有向 Roslyn 文件夹 (CodeDom) 发布任何内容。有什么建议或建议吗?
【问题讨论】:
WCF 在你的项目中是必须的吗?它的服务/地址概念过于复杂,您应该会发现 ASP.NET Web API(当然是今天的 ASP.NET Core)是一个更简单的选择(并且更符合 IIS 概念)。请记住,.NET Core 是未来,而未来不包括 WCF。 感谢 Marc 和 Lex。不,WCF 不是“必备”选项。这是一个教会团体的志愿者项目,其中 db 是一个可以查询和更新的成员列表。该数据库现在保存在 Google Drive“Sheets”应用程序中。我正在开发一个 WinForms 应用程序,该应用程序可用于编辑和维护该数据库的副本。最初,我将我的 WinForms 应用程序设计为使用 MS Access 数据库。由于我熟悉 DataGridView、ADO.NET 和数据绑定,我正在寻找我的 WinForms 客户端可以使用的远程数据库选项。你能多谈谈你的建议吗? WinForms 仍然是 .NET Core 的一部分,因此您可以很好地使用它。只是 WCF 不再是后端服务的有效选项,您应该为此使用 ASP.NET Core。 dot.net 有很多值得挖掘的地方。 【参考方案1】:根据您的描述,我发现当您将服务发布到IIS时,您的配置文件中仍然存在host标签。只有像 Windows 服务这样的自托管或托管程序需要配置主机。在 IIS 中托管服务时,服务的基地址由部署在 IIS 中的端口号和服务的文件名组成。
这是部署在 IIS 中的 WCF 服务的配置文件。
我将服务的端口号设置为8063。
访问此地址,我们将看到服务的目录。
点击service1.scv可以看到服务正常启动。此时地址栏中的“localhost:8063/Service1.svc”就是服务的地址。客户端需要访问这个地址才能成功。
更新
如果您的项目部署在 IIS 中,我建议在创建项目时使用 WCF 服务应用程序模板。
创建后的结构目录是这样的:
Service1 是服务的实现类。
【讨论】:
谢谢丁,我更改了web.config以删除我无法部署 IIS 托管解决方案,因此我将策略更改为使用自托管 Windows 窗体项目作为托管应用程序。
我将我的服务项目从 VS2017 .NET4.5.2 WCF 服务库模板更改为 WCF 服务应用程序模板,并且更成功地让我的整体解决方案在开发/调试模式下工作。 但是,我无法正确发布/部署我的解决方案以让 IIS 托管服务。 因此,我改为使用 Windows 窗体“自托管”方法。这符合我能够使用 Windows 窗体控件的最终目标,并且它现在适用于预期的用户组.
这是我所做的:
将我的服务项目更改为 WCF 服务应用程序模板。
在 .NET 4.5.2 中,*.SVC 文件不是必需的,但接口和实现是必需的。
移除 IIS Host Solution 文件夹,将 Windows Forms 项目添加为 Service Hosting 应用程序。
将 Service 的 Web.config 复制到 HostWinFormsApp 项目,将其重命名为 App.config。
对托管项目的 App.config 进行了更改,使其具有 “serviceHostingEnvironment”部分
为其添加了“serviceActivations”部分,指向托管项目中的基地址 像这样:relativeAddress="./HostWinFormsApp/MemberService.svc"
在 Service 项目中添加了几乎相同的 Web.config,但使用简单 仅 relativeAddress="./MemberService.svc"
通过 HostWinFormsApp 和服务应用程序的配置文件更正,我能够 启动服务,运行 SVCUTIL.exe 并为 UI 创建我的服务代理。这 实用程序还使用端点地址更新了 UI 客户端的 app.config:
将 ServiceHost 对象添加到 HostWinFormsApp.Program.cs Main() 函数以托管和启动 WCF 服务“ACTSFactoryWCFServiceApp.MemberService”。
向 UI 客户端的 Program.cs Main() 函数添加 System.Diagnostic.Process 以启动 在“运行” UI 客户端的 winform 之前的托管应用程序 HostWinFormsApp (Form1)。
配置文件更正后,新的 HostWinFormsApp 项目就位 定义了一个 ServiceHost 对象并且 UI 客户端项目启动 HostWinFormsApp,我准备测试了。
将 HostWinFormsApp 和 UI Client 设置为启动项目,并且 ctrl-F5 去测试。两个 winform 都启动了,先托管项目,然后是客户端。
将启动项目更改为仅 UI 客户端和 Ctrl-F5。两个winforms都开始了, 托管第一,客户第二。客户端在 ADGView 中请求和接收的数据 控制。
在 UI Client、Service 和 HostWinFormsApp 项目的 Properties 页面“Build events - Post-build" 选项,添加了将 DLL 文件从 bin\debug 复制上一级的命令 到 .\bin 文件夹。清洁和重建解决方案。 (复制 .\*.* ..\*.*)
右键单击服务项目,发布到目标文件夹。发布文件夹\bin 是 创建包括从服务项目复制到 .\bin 的所有 DLL。服务 Web.config 已复制到发布文件夹。
已将 HostWinFormsApp 项目作为 StartUpProject 发布到相同的 pub 文件夹。安装程序.exe, HostWinFormsApp.application 和子文件夹“Application”是在 pub 文件夹中创建的。 宿主项目的 DLL 被复制到“应用程序” 文件夹。
将“setup.exe”重命名为“Host.exe”并以管理员身份运行以完成设置。
已将 ACTSFactoryUI(Windows 窗体)客户端项目作为 StartUpProject 发布到 pub 文件夹。安装程序.exe, ACTSFactoryUI.application 已创建,ACTSFactoryUI 项目 DLL 进入“Application”文件夹。
将“Setup.exe”重命名为“Client.exe”并双击完成设置。
创建了一个“RunApps.bat”文件来启动这两个应用程序。为 c:\pub-folder\RunApps.bat 创建了一个桌面快捷方式,在快捷方式中编辑了“高级”以以管理员身份运行。
双击快捷方式,Host.exe 和 Client.exe 启动。
下面的屏幕截图显示了服务、UI 客户端、部署文件夹和桌面上的“快捷方式”图标。
-
下一张图片显示了托管 WinForms 项目的 Program.cs 类。在这堂课中,
定义了 ServiceHost 对象,带有 Service 类型和基地址
服务,然后打开服务主机 - 启动服务运行
(监听)请求。
-
完成此 (localdb) 部署后,我必须删除并重新加载我的 EntityFramework,并使用远程数据库作为我的源在 DAL 层中重建实体模型类。一旦远程数据库的新连接和实体模型完成,并且所有配置文件都使用新的连接字符串更新,我以与上述相同的方式重新部署到我的笔记本电脑 - 现在本地安装的服务访问远程数据库。这是一个 EF DB Model First 实现。 SQL Server 数据库是在 MS SSMS 中构建的。
【讨论】:
以上是关于WCF / EF / SQL Server / VS2017 / C#:多层应用程序在部署到本地 IIS 10.0 作为托管服务器时出错的主要内容,如果未能解决你的问题,请参考以下文章
使用 wcf 对 sql server 运行查询时出现奇怪的错误
Windows Azure 上的 WCF 服务 - 连接到本地 SQL Server 数据库
如何在 Sql Server 上设置安全性以允许 WCF 服务访问?