【问题标题】:WCF Service with Castle Windsor dependency injection hosted in IISIIS 中托管的带有 Castle Windsor 依赖注入的 WCF 服务
【发布时间】:2013-09-20 13:12:29
【问题描述】:

我第一次尝试创建 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

最后,我在 Controller 中添加了一些测试代码,看看是否可以让 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 注册了一个端点。

我觉得我很接近这个,但已经碰到了众所周知的砖墙。任何帮助将不胜感激。如果有任何其他信息可以提供给您,请告诉我。

非常感谢,

【问题讨论】:

    标签: wcf asp.net-mvc-4 iis-7.5 castle-windsor


    【解决方案1】:

    当您的服务中存在错误配置时,该错误是一个相当普遍的错误。该服务根本没有正常运行并返回一个标准的 wcf html 错误页面 - 客户端期待一个 soap 响应,但它得到的只是错误 html。

    要找出真正的错误,您应该在浏览器中导航到您的服务

    http://localhost:8732/Design_Time_Addresses/DataWarehouseWCFService/GetRiskDataService/GetRiskDataService.svc
    

    此处显示的错误消息将更具描述性。

    看看你目前发布的内容,可能与...有关。

    • 您的风险等级是否标记为具有 DataMember 属性的 DataContract?
    • 您可能不需要端点地址上的 address="../GetRiskDataService.svc" 部分

    【讨论】:

    • 您好,马特,感谢您的回复。我没有用这些属性标记我的风险等级,因为我在某处读到,对于简单的 POCO 类,这些将在没有属性的情况下正确序列化。添加它们没有任何区别。我还从我的 app.config 文件中取出了端点地址属性。再次没有运气。
    • 您建议的网址与我使用的网址大不相同。仅将您的 URL 粘贴到浏览器中是行不通的。请问你这个网址是怎么想出来的?非常感谢,阿什。
    • 在您的服务的 app.config 中,您有一个指定为“localhost:8732/Design_Time_Addresses/DataWarehouseWCFService/…”的基地址 - 加上您的 svc 文件名 GetRiskDataService.svc
    • 尝试在您的其他端点下添加“”。在浏览器中获得响应是进行这项工作的良好的第一步。另外,你用的是什么网址?
    • 那个基地址是由 Visual Studio 设计者添加的——与我无关!我将重新添加元数据。我使用的 URL 的格式为 http://[Server Name].[Domain Name]/Data Warehouse Web Services/GetRiskDataService.svc
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多