“多个过滤器匹配。”在 WCF 中对多个端点使用相同的地址时

发布于 2024-12-20 17:13:55 字数 4483 浏览 2 评论 0原文

因此,出于一些组织方面的考虑,我将最初的单个接口合约拆分为两个单独的接口合约。现在,我只有一个类实现这两个接口,并且我希望通过 WCF 将它们全部用作 REST 服务。 下面列出了合同:

第一:

[ServiceContract]
public interface INotification
{
    [OperationContract]
    [WebGet]
    XElement GetInfo(string appID);
    [OperationContract]
    [WebGet]
    void RegisterRID(string appID, string registrationID);
}

第二:

[ServiceContract]
public interface IPlanning
{
    [OperationContract]
    [WebGet]
    XElement PlanTrip(string toDestination, string fromDestination, int year, int month, int day, int hour, int minute, string appID);
    [OperationContract]
    [WebGet]
    XElement PlanTripDelayed(string toDestination, string fromDestination, int year, int month, int day, int hour, int minute, string appID);
    [OperationContract]
    [WebGet]
    XElement PlanTripLoc(string toDestination, string fromLat, string fromLong, int year, int month, int day, int hour, int minute, string appID);
}

我的 app.config 如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
  <behaviors>
    <endpointBehaviors>
      <behavior name="RESTFriendly">
        <webHttp />
      </behavior>
    </endpointBehaviors>
  </behaviors>
    <services>
        <service name="TravelPlannerWebService.Domain.Entity.ETravelPlanner">
            <endpoint binding="webHttpBinding" bindingConfiguration="" contract="TravelPlannerWebService.Acquaintance.IPlanning" behaviorConfiguration="RESTFriendly" />
            <endpoint binding="webHttpBinding" bindingConfiguration="" contract="TravelPlannerWebService.Acquaintance.INotification" behaviorConfiguration="RESTFriendly" />
            <host>
                <baseAddresses>
                    <add baseAddress="http://localhost:80" />
                </baseAddresses>
            </host>
        </service>
    </services>
</system.serviceModel>

问题是,每当我尝试使用两个接口时,都会收到错误。通过查看我的 app_tracelog.svclog (我在这里故意从 app.config 中删除了调试代码),我可以看到出现以下错误:

消息:多个过滤器匹配。

堆栈跟踪:

System.ServiceModel.Dispatcher.EndpointDispatcherTable.LookupInCache(Message message, Boolean&amp; addressMatched)
System.ServiceModel.Dispatcher.EndpointDispatcherTable.Lookup(Message message, Boolean&amp; addressMatched)
System.ServiceModel.Dispatcher.ChannelHandler.GetDatagramChannel(Message message, EndpointDispatcher&amp; endpoint, Boolean&amp; addressMatched)
System.ServiceModel.Dispatcher.ChannelHandler.EnsureChannelAndEndpoint(RequestContext request)
           System.ServiceModel.Dispatcher.ChannelHandler.TryRetrievingInstanceContext(RequestContext request)
System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext request, OperationContext currentOperationContext)
System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result)
System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult result)
System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
System.Runtime.AsyncResult.Complete(Boolean completedSynchronously)
System.Runtime.InputQueue`1.AsyncQueueReader.Set(Item item)
System.Runtime.InputQueue`1.EnqueueAndDispatch(Item item, Boolean canDispatchOnThisThread)
System.Runtime.InputQueue`1.EnqueueAndDispatch(T item, Action dequeuedCallback, Boolean canDispatchOnThisThread)
System.ServiceModel.Channels.SingletonChannelAcceptor`3.Enqueue(QueueItemType item, Action dequeuedCallback, Boolean canDispatchOnThisThread)
System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, Action callback)
System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore(IAsyncResult result)
System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContext(IAsyncResult result)
System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
System.Net.LazyAsyncResult.Complete(IntPtr userToken)
System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
System.Net.ListenerAsyncResult.WaitCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

我不知道如何解决这个问题。据我所知,从以下指南来看,这是对多个端点使用相同类型的正确方法。有什么想法吗?

So, due to some organizational concerns, I've split up what was intially a single interface contract into two seperate ones. Now, I have only one class implementing both interfaces, and I want to make them all available as REST-services through WCF.
The contracts are listed below:

1st:

[ServiceContract]
public interface INotification
{
    [OperationContract]
    [WebGet]
    XElement GetInfo(string appID);
    [OperationContract]
    [WebGet]
    void RegisterRID(string appID, string registrationID);
}

2nd:

[ServiceContract]
public interface IPlanning
{
    [OperationContract]
    [WebGet]
    XElement PlanTrip(string toDestination, string fromDestination, int year, int month, int day, int hour, int minute, string appID);
    [OperationContract]
    [WebGet]
    XElement PlanTripDelayed(string toDestination, string fromDestination, int year, int month, int day, int hour, int minute, string appID);
    [OperationContract]
    [WebGet]
    XElement PlanTripLoc(string toDestination, string fromLat, string fromLong, int year, int month, int day, int hour, int minute, string appID);
}

My app.config looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
  <behaviors>
    <endpointBehaviors>
      <behavior name="RESTFriendly">
        <webHttp />
      </behavior>
    </endpointBehaviors>
  </behaviors>
    <services>
        <service name="TravelPlannerWebService.Domain.Entity.ETravelPlanner">
            <endpoint binding="webHttpBinding" bindingConfiguration="" contract="TravelPlannerWebService.Acquaintance.IPlanning" behaviorConfiguration="RESTFriendly" />
            <endpoint binding="webHttpBinding" bindingConfiguration="" contract="TravelPlannerWebService.Acquaintance.INotification" behaviorConfiguration="RESTFriendly" />
            <host>
                <baseAddresses>
                    <add baseAddress="http://localhost:80" />
                </baseAddresses>
            </host>
        </service>
    </services>
</system.serviceModel>

Problem being, whenever I try to use two interfaces, I get an error. Through looking at my app_tracelog.svclog (I've removed debug code from app.config intentionally here), I can see that I get the following error:

Message: Multiple filters matched.

Stack Trace:

System.ServiceModel.Dispatcher.EndpointDispatcherTable.LookupInCache(Message message, Boolean& addressMatched)
System.ServiceModel.Dispatcher.EndpointDispatcherTable.Lookup(Message message, Boolean& addressMatched)
System.ServiceModel.Dispatcher.ChannelHandler.GetDatagramChannel(Message message, EndpointDispatcher& endpoint, Boolean& addressMatched)
System.ServiceModel.Dispatcher.ChannelHandler.EnsureChannelAndEndpoint(RequestContext request)
           System.ServiceModel.Dispatcher.ChannelHandler.TryRetrievingInstanceContext(RequestContext request)
System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext request, OperationContext currentOperationContext)
System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result)
System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult result)
System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
System.Runtime.AsyncResult.Complete(Boolean completedSynchronously)
System.Runtime.InputQueue`1.AsyncQueueReader.Set(Item item)
System.Runtime.InputQueue`1.EnqueueAndDispatch(Item item, Boolean canDispatchOnThisThread)
System.Runtime.InputQueue`1.EnqueueAndDispatch(T item, Action dequeuedCallback, Boolean canDispatchOnThisThread)
System.ServiceModel.Channels.SingletonChannelAcceptor`3.Enqueue(QueueItemType item, Action dequeuedCallback, Boolean canDispatchOnThisThread)
System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, Action callback)
System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore(IAsyncResult result)
System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContext(IAsyncResult result)
System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
System.Net.LazyAsyncResult.Complete(IntPtr userToken)
System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
System.Net.ListenerAsyncResult.WaitCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

I have no idea how to solve this. As far as I can see, from following guides, this is the correct way to use the same type for multiple endpoints. Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

阳光①夏 2024-12-27 17:13:55

您可以使用以下命令并查看是否仍然出现异常:

<service name="TravelPlannerWebService.Domain.Entity.ETravelPlanner">
        <endpoint address="" binding="webHttpBinding" bindingConfiguration="" contract="TravelPlannerWebService.Acquaintance.IPlanning" behaviorConfiguration="RESTFriendly" />
        <endpoint address="more" binding="webHttpBinding" bindingConfiguration="" contract="TravelPlannerWebService.Acquaintance.INotification" behaviorConfiguration="RESTFriendly" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:80" />
          </baseAddresses>
        </host>
      </service>

您不能让 2 个不同的端点侦听同一地址。因此,我添加了地址属性来区分它们。

当托管在 IIS 中时,您的 URL 可能如下所示:

http://localhost/ApplicationVD/PlanTrip
http://localhost/ApplicationVD/PlanTripDelayed
http://localhost/ApplicationVD/PlanTripLoc
http://localhost/ApplicationVD/More/GetInfo
http://localhost/ApplicationVD/More/RegisterRID

Can you use the below and see if you still get an exception:

<service name="TravelPlannerWebService.Domain.Entity.ETravelPlanner">
        <endpoint address="" binding="webHttpBinding" bindingConfiguration="" contract="TravelPlannerWebService.Acquaintance.IPlanning" behaviorConfiguration="RESTFriendly" />
        <endpoint address="more" binding="webHttpBinding" bindingConfiguration="" contract="TravelPlannerWebService.Acquaintance.INotification" behaviorConfiguration="RESTFriendly" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:80" />
          </baseAddresses>
        </host>
      </service>

You cannot have 2 different endpoints listening on the same address. Hence, I have added the address attribute to distinguish them.

Your URLs might be as follows when hosted in IIS:

http://localhost/ApplicationVD/PlanTrip
http://localhost/ApplicationVD/PlanTripDelayed
http://localhost/ApplicationVD/PlanTripLoc
http://localhost/ApplicationVD/More/GetInfo
http://localhost/ApplicationVD/More/RegisterRID
对不⑦ 2024-12-27 17:13:55

简而言之,您需要记住 Indigo 的 ABC ... 咳咳 ... WCF:地址、绑定、合约。

事实上,您的服务的端点在同一物理类中实现,这与您的服务的调用者无关:对于外界来说,您的服务现在通过两个不同的服务端点公开:IPlanning 和 IPlanning。 I通知。

修改您的 app.config 文件的端点,以在其自己的地址(相对于您的服务的基地址)公开每个服务端点:

<endpoint name ="TripPlanningEndpoint" 
    address="Planning" binding="webHttpBinding" contract="Service.IPlanning" 
    behaviorConfiguration="RESTFriendly" />

<endpoint name="TripNotificationsEndpoint" 
    address="Notifications" binding="webHttpBinding" contract="Service.INotification" 
    behaviorConfiguration="RESTFriendly" />

哦...您不需要所有 REST 友好端点行为内容 - webHttpBinding 默认情况下已经支持 httpGet。 :)

另外,我强烈鼓励您启用服务元数据(尤其是在开发时),因为这允许您使用工具生成客户端代理类,以便您快速构建(正确配置)客户端应用程序和测试。

在服务的 app.config 类中,添加以下内容:

<system.serviceModel>
    <behaviors>
     ...
        <serviceBehaviors>
            <behavior name="ServiceMetadataBehavior">
                <serviceMetadata httpGetEnabled="true"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>

还添加一个附加端点以公开服务的元数据:

<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />

现在,您可以使用“添加服务引用”添加对客户端/测试应用程序的引用:
多接口 WCF 服务 - 添加引用对话框

HTH。

The short answer here is that you need to remember the ABC of Indigo ... ahem ... WCF: Address, Binding, Contract.

The fact that your service's endpoints are implemented within the same physical class is irrelevant to your service's callers: To the outside world, your service is now exposed via two distinct service endpoints: IPlanning & INotification.

Modify your app.config file's endpoints to expose each service endpoint at its own address (relative to your service's base address):

<endpoint name ="TripPlanningEndpoint" 
    address="Planning" binding="webHttpBinding" contract="Service.IPlanning" 
    behaviorConfiguration="RESTFriendly" />

<endpoint name="TripNotificationsEndpoint" 
    address="Notifications" binding="webHttpBinding" contract="Service.INotification" 
    behaviorConfiguration="RESTFriendly" />

Oh ... and you don't need all the REST Friendly endpoint behavior stuff - webHttpBinding already supports httpGet by default. :)

Also, I strongly encourage you to enable service metadata (esp' while developing) as this allows you to use tools to generate the client-side proxy classes to allow you to quickly build (properly configured) client apps and tests.

To your service's app.config class, add the following:

<system.serviceModel>
    <behaviors>
     ...
        <serviceBehaviors>
            <behavior name="ServiceMetadataBehavior">
                <serviceMetadata httpGetEnabled="true"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>

Also add an additional endpoint to expose your service's metadata:

<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />

Now you can add references to your client/test apps using "Add Service Reference":
Multi-interface WCF Service - Add Reference Dialog

HTH.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文