使用唯一ListenUri与WCF发现时出现To和Via URI必须匹配错误
解决BasicHttpBinding下To和Via URI必须相同的错误
这个错误的根源很明确:你使用的BasicHttpBinding默认采用AddressingVersion.None(不支持WS-Addressing规范),这种绑定要求请求的目标地址(To)和路由地址(Via)必须完全一致。而你设置了ListenUriMode.Unique让服务生成了唯一的监听Uri,客户端又通过ClientViaBehavior指定了这个监听Uri作为Via,同时保留原服务地址作为To,这就触发了绑定的限制条件。
下面给你两种可行的解决方案,根据你的需求选择:
方案一:改用支持WS-Addressing的绑定(推荐)
如果你的场景允许,换成WSHttpBinding(默认支持WS-Addressing),这样就能支持To和Via不同的情况,同时满足你设置ListenUriMode.Unique和保护级别为None的需求。
服务端代码修改:
Uri baseAddress = new Uri("http://localhost/" + Guid.NewGuid().ToString() + "/"); ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService), baseAddress); try { // 创建WSHttpBinding并设置安全模式为None(匹配保护级别要求) var binding = new WSHttpBinding(SecurityMode.None); binding.Security.Message.ClientCredentialType = MessageCredentialType.None; binding.Security.Message.EstablishSecurityContext = false; ServiceEndpoint endpoint = serviceHost.AddServiceEndpoint(typeof(ICalculatorService), binding, string.Empty); endpoint.ListenUriMode = ListenUriMode.Unique; serviceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior()); serviceHost.AddServiceEndpoint(new UdpDiscoveryEndpoint()); serviceHost.Open(); Console.WriteLine("Calculator Service started at {0}", baseAddress); Console.ReadLine(); } catch (CommunicationException e) { Console.WriteLine(e.Message); }
客户端InvokeCalculatorService方法修改:
// 改用WSHttpBinding匹配服务端 CalculatorServiceClient client = new CalculatorServiceClient(new WSHttpBinding(SecurityMode.None), endpointAddress); Console.WriteLine("Invoking CalculatorService at {0}", endpointAddress.Uri); if (viaUri != null) { client.Endpoint.Behaviors.Add(new ClientViaBehavior(viaUri)); Console.WriteLine("Using the viaUri {0}", viaUri); } // 后续调用逻辑不变...
方案二:继续使用BasicHttpBinding,直接用ListenUri作为目标地址
如果必须保留BasicHttpBinding,那就要放弃ClientViaBehavior,直接将服务的监听Uri作为客户端请求的目标地址(To),这样To和Via就会自动一致。
客户端代码修改:
if (findResponse.Endpoints.Count > 0) { EndpointDiscoveryMetadata discoveredEndpoint = findResponse.Endpoints[0]; if (discoveredEndpoint.ListenUris.Count > 0 && discoveredEndpoint.Address.Uri != discoveredEndpoint.ListenUris[0]) { // 直接用ListenUri创建EndpointAddress,不再使用ClientViaBehavior InvokeCalculatorService(new EndpointAddress(discoveredEndpoint.ListenUris[0]), null); } else { InvokeCalculatorService(discoveredEndpoint.Address, null); } }
这样修改后,客户端请求的目标地址就是服务实际监听的Uri,完全符合BasicHttpBinding的要求,错误就会消失。
内容的提问来源于stack exchange,提问作者A.Learn
相关产品推荐
相关产品推荐

