我第一次尝试创建 WCF 服务,以托管在带有 IIS 的服务器上。该服务将依赖一个单独的类来从 SQL 数据库中检索数据,因此我尝试使用 Castle Windsor 通过 IoC 保持这种松散耦合。
以下是 WCF 服务的各个方面(提前向任何 C#ers 道歉,但我是 VB 人!):
服务合约
<ServiceContract()> _
Public Interface IGetRiskDataService
<OperationContract()>
Function GetRisksByInsuredOpenBoxID(ByVal openBoxID As String) As List(Of Risk)
End Interface
Risk是我自己的类,用于包含从数据库中检索到的数据。
服务合同的执行
Public Class GetRiskDataService : Implements IGetRiskDataService
Private _rep As IDataWarehouseRepository
Public Sub New(ByVal rep As IDataWarehouseRepository)
_rep = rep
End Sub
Public Function GetRisksByInsuredOpenBoxID(openBoxID As String) As List(Of Risk) Implements IGetRiskDataService.GetRisksByInsuredOpenBoxID
Return _rep.GetRisksByInsuredOpenBoxID(CType(openBoxID, Integer))
End Function
End Class
如您所见,我将用于从 SQL 数据库获取数据的类注入到 WCF 服务的构造函数中。
.svc 文件
<% @ServiceHost Service="DataWarehouseWCFService.GetRiskDataService" Factory="Castle.Facilities.WcfIntegration.DefaultServiceHostFactory, Castle.Facilities.WcfIntegration" %>
App.config 文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<system.serviceModel>
<services>
<service behaviorConfiguration="DataWarehouseWCFService.GetRiskDataServiceBehavior"
name="DataWarehouseWCFService.GetRiskDataService">
<!--<endpoint address="" binding="wsHttpBinding" contract="DataWarehouseWCFService.IGetRiskDataService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>-->
<!--<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />-->
<endpoint address="../GetRiskDataService.svc"
binding="webHttpBinding"
contract="DataWarehouseWCFService.IGetRiskDataService"
behaviorConfiguration="webBehaviour" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/DataWarehouseWCFService/GetRiskDataService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DataWarehouseWCFService.GetRiskDataServiceBehavior">
<!-- To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="False"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webBehaviour">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
我认为这里的一切都还可以,除了 App.config 文件,我基本上没有留下任何东西。
然后,我创建了一个基本的 ASP.Net Web 应用程序,该应用程序将驻留在 IIS 服务器上以托管服务。在 Web 应用程序中,global.asax 文件如下所示:
Private _container As IWindsorContainer
Private _sqlConnection As String = "Data Source=[Server Name];Integrated Security=SSPI;Initial Catalog=[Database Name];"
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
' Fires when the application is started
_container = New WindsorContainer
_container.AddFacility(Of WcfFacility).Register(Component.For(Of IDataWarehouseRepository).ImplementedBy(Of SQLDataWarehouseRepository).DependsOn(Dependency.OnValue("connect", _sqlConnection)), _
Component.For(Of IGetRiskDataService).ImplementedBy(Of GetRiskDataService))
End Sub
所以这里我向Castle Windsor注册服务,包括对SQL数据检索类的依赖。希望到目前为止,一切都很好......
我已经在 IIS 服务器上部署并安装了这个托管应用程序,没有任何问题。
所以剩下的就是在客户端应用程序中使用服务,这就是我遇到的问题。我有一个 MVC4 应用程序,我希望在其中使用 Web 服务在视图中显示数据。我已经在这个应用程序中使用 Castle Windsor 来注册其他依赖项,因此所需的所有 Castle Windsor 基础设施都已经存在。因此,我认为我需要的只是 Web 服务的安装程序。我的尝试如下:
Public Class DataWarehouseWebServicesInstaller : Implements IWindsorInstaller
Private Const _getRiskDataServiceEndpoint As String = "http://[Server Name].[Domain Name]/Data Warehouse Web Services/GetRiskDataService.svc"
Public Sub Install(container As Castle.Windsor.IWindsorContainer, store As Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore) Implements Castle.MicroKernel.Registration.IWindsorInstaller.Install
'Data Warehouse Web Services
container.Register(Component.For(Of IEndpointBehavior).ImplementedBy(Of WebHttpBehavior))
container.AddFacility(Of WcfFacility).Register( _
Component.For(Of IGetRiskDataService).AsWcfClient( _
New DefaultClientModel( _
WcfEndpoint.BoundTo(New WebHttpBinding).At(_getRiskDataServiceEndpoint) _
) _
) _
)
End Sub
End Class
最后,我向控制器添加了一些测试代码,看看是否可以让 WCF 服务工作:
Public Sub New(ByVal ash As IGetRiskDataService)
Dim lozza = ash.GetRisksByInsuredOpenBoxID(100005859)
For Each lianne As Risk In lozza
Dim neil As Date = lianne.ExpiryDate.CalendarDate
Next
End Sub
在对此进行测试时,我收到以下错误:
{"The remote server returned an error: (415) Cannot process the message because the content type 'application/xml; charset=utf-8' was not the expected type 'text/xml; charset=utf-8'.."}. The client and service bindings may be mismatched.
这就是我迷路的地方。我已经研究过客户端和服务绑定不匹配的问题,但不幸的是,几乎每个答案都提到了在 app.config 文件中指定的这些绑定,我没有这样做,因为我依靠 Castle Windsor 来处理大部分问题,以及任何我做的配置我想在代码中做。例如,在我的安装程序代码中,我使用 WebHttpBinding 注册了一个端点。
我觉得我很接近这一点,但已经碰到了众所周知的砖墙。任何帮助将不胜感激。如果有任何其他信息可以提供给您,请告诉我。
非常感谢,
灰