【问题标题】:In a WCF Service, how can I expose a second endpoint with access to only certain methods?在 WCF 服务中,如何公开第二个端点,只能访问某些方法?
【发布时间】:2011-12-09 21:48:22
【问题描述】:

我有一项服务,它有一系列用于为我们的网站创建和管理资产的方法。它还有两个需要外部访问的方法,比如说“GetConfiguration”和“GetElement”。我想使用不同的 ServiceContract 在不同的端点公开相同的服务。但我希望这两种方法在两个端点都可用。

这是我的 App.Config 的相关部分:

  <service name="Manager.Manager" behaviorConfiguration="Manager.ManagerBehavior">
    <endpoint address="" binding="customBinding" bindingConfiguration="NetHttpBinding" contract="Manager.IManager" />
    <endpoint address="Runtime" binding="customBinding" bindingConfiguration="NetHttpBinding" contract="Manager.IPublicManager" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
  </service>

当我将这个东西加载到 IIS 并尝试访问它时,我收到以下错误:

 An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is:
 System.InvalidOperationException: An exception was thrown in a call to a WSDL export extension: System.ServiceModel.Description.DataContractSerializerOperationBehavior
 contract: http://tempuri.org/:IPublicManager ----> System.InvalidOperationException: The Manager.IPublicManager.GetConfiguration operation references a message element [http://tempuri.org/:GetConfiguration] that has already been exported from the Manager.IManager.GetConfiguration operation. You can change the name of one of the operations by changing the method name or using the Name property of OperationContractAttribute. Alternatively, you can control the element name in greater detail using the MessageContract programming model.
 at System.ServiceModel.Description.MessageContractExporter.AddElementToSchema(XmlSchemaElement element, String elementNs, XmlSchemaSet schemaSet)
 at System.ServiceModel.Description.MessageContractExporter.ExportWrappedPart(Message message, String elementName, String elementNs, XmlSchemaSet schemaSet, Boolean skipSchemaExport)
 at System.ServiceModel.Description.DataContractSerializerMessageContractExporter.ExportBody(Int32 messageIndex, Object state)
 at System.ServiceModel.Description.MessageContractExporter.ExportMessage(Int32 messageIndex, Object state)
 at System.ServiceModel.Description.MessageContractExporter.ExportMessageContract()
 at System.ServiceModel.Description.WsdlExporter.CallExtension(WsdlContractConversionContext contractContext, IWsdlExportExtension extension)
 --- End of inner ExceptionDetail stack trace ---
 at System.ServiceModel.Description.WsdlExporter.CallExtension(WsdlContractConversionContext contractContext, IWsdlExportExtension extension)
 at System.ServiceModel.Description.WsdlExporter.CallExportContract(WsdlContractConversionContext contractContext)
 at System.ServiceModel.Description.WsdlExporter.ExportContract(ContractDescription contract)
 at System.ServiceModel.Description.WsdlExporter.ExportEndpoint(ServiceEndpoint endpoint, XmlQualifiedName wsdlServiceQName)
 at System.ServiceModel.Description.WsdlExporter.ExportEndpoints(IEnumerable`1 endpoints, XmlQualifiedName wsdlServiceQName)
 at System.ServiceModel.Description.ServiceMetadataBehavior.MetadataExtensionInitializer.GenerateMetadata()
 at System.ServiceModel.Description.ServiceMetadataExtension.EnsureInitialized()
 at System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.InitializationData.InitializeFrom(ServiceMetadataExtension extension)
 at System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.GetInitData()
 at System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.TryHandleDocumentationRequest(Message httpGetRequest, String[] queries, Message& replyMessage)
 at System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.ProcessHttpRequest(Message httpGetRequest)
 at SyncInvokeGet(Object , Object[] , Object[] )
 at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
 at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
 at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
 at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
 at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

所以它不喜欢操作具有相同的名称。有任何想法吗?他们都使用相同的服务类。也许我只是以完全错误的方式解决问题?

【问题讨论】:

    标签: .net wcf iis


    【解决方案1】:

    虽然这并不能完全解决您的问题,但我希望它可以对您有所帮助。我使用webHttpBinding,因为我最熟悉它。

    这里的想法是将公共和私有功能分成两个独立的接口:

    [ServiceContract]
    public interface IPrivate  : IPublic
    {
        [WebGet(UriTemplate = "/admin")]
        [OperationContract]
        int PrivateStuff();
    }
    
    [ServiceContract]
    public interface IPublic
    {
        [WebGet(UriTemplate = "/common")]
        [OperationContract]
        int PublicStuff();
    }
    

    正如您所见,IPrivate 的实现者还必须实现 IPublic,为什么服务实现 IPrivate 才能同时公开。

    现在可以将服务实现公开为IPublic 和IPrivate,并且可以在服务下方公开端点(“service1.svc”):

        <system.serviceModel>
          <behaviors>
            <serviceBehaviors>
              <behavior>
                <serviceMetadata httpGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="false"/>
              </behavior>
            </serviceBehaviors>
            <endpointBehaviors>
              <behavior name="rest">
                <webHttp/>
              </behavior>
            </endpointBehaviors>
          </behaviors>
          <services>
            <service name="ManagerService.Service">
              <endpoint address="private" behaviorConfiguration="rest" contract="ManagerService.IPrivate" binding="webHttpBinding"/>
              <endpoint address="public" behaviorConfiguration="rest" contract="ManagerService.IPublic" binding="webHttpBinding" />
              <endpoint address="/private/mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
              <endpoint address="/public/mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
            </service>
          </services>
    

    该服务现在公开在http://host/service1.svc/common,而私有版本公开在http://host/service1.svc/admin

    元数据交换似乎无法正常工作,但这可能是由于绑定类型。

    【讨论】:

      【解决方案2】:

      1) 创建两个带有服务契约属性的接口/契约。 2)在服务中执行两个合同。 3)虽然服务相同,但创建端点并提及不同的合同名称(接口)。

      更多信息请查看链接

      https://www.safaribooksonline.com/library/view/learning-wcf/9780596101626/ch01s07.html

      【讨论】:

        猜你喜欢
        • 2012-10-26
        • 2011-03-03
        • 1970-01-01
        • 2012-06-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多