Can't access WCF service after versioning service contracts - c#

I'm having trouble figuring out an issue with a WCF service that has appeared after I have implemented a "v2" contract to it to extend functionality. Everything builds fine but when I try to access the service in the browser I just get told that it cannot connect. When I try to add it as a service reference I get a similar message regarding connection issues. However, when I remove the extended contract's endpoint from the config file, and leave the previous "v1" version intact, it works fine.
Here is the "v1" contract:
namespace Company.Services.Ticketing.Retail.Contracts
{
[ServiceContract(Name = "OutletReportingContract_v1", Namespace = "https://enterprise.company.ie/Services/Retail")]
public interface IOutletReportingContract_v1
{
/* methods */
}
}
And here is the "v2" contract:
namespace Company.Services.Ticketing.Retail.Contracts
{
[ServiceContract(Name = "OutletReportingContract_v2", Namespace = "https://enterprise.company.ie/Services/Retail")]
public interface IOutletReportingContract_v2 : IOutletReportingContract_v1
{
/* methods */
}
}
Here are the endpoints in the Web.config:
<service name="Company.Services.Ticketing.Retail.OutletService" behaviorConfiguration="Public">
<endpoint address="1" binding="wsHttpBinding" bindingConfiguration="Standard" name="OutletReportingContract_v1"
contract="Company.Services.Ticketing.Retail.Contracts.IOutletReportingContract_v1" />
<endpoint address="2" binding="wsHttpBinding" bindingConfiguration="Standard" name="OutletReportingContract_v2"
contract="Company.Services.Ticketing.Retail.Contracts.IOutletReportingContract_v2" />
<endpoint address="mex" binding="mexHttpsBinding" name="IMetadataExchange" contract="IMetadataExchange" />
</service>
And here is the error message that appears in the event viewer:
WebHost failed to process a request.
Sender Information: System.ServiceModel.Activation.HostedHttpRequestAsyncResult/28075619
Exception: System.Web.HttpException (0x80004005): There was no channel actively listening at 'https://phil-pc.company.local/Services/Retail/OutletService.svc/_vti_bin/ListData.svc/$metadata'. This is often caused by an incorrect address URI. Ensure that the address to which the message is sent matches an address on which a service is listening. ---> System.ServiceModel.EndpointNotFoundException: There was no channel actively listening at 'https://phil-pc.company.local/Services/Retail/OutletService.svc/_vti_bin/ListData.svc/$metadata'. This is often caused by an incorrect address URI. Ensure that the address to which the message is sent matches an address on which a service is listening.
at System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult result)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest()
at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result)
Process Name: w3wp
Process ID: 8148
A bit stumped now and would appreciate any help :)

You need to separate your services declaration in web.config.
Assuming your implementation classes are named OutletService_v1 & OutletService_v2 you should end up with something like that:
<services>
<service name="Company.Services.Ticketing.Retail.OutletService_v1" behaviorConfiguration="Public">
<endpoint binding="wsHttpBinding" bindingConfiguration="Standard" contract="Company.Services.Ticketing.Retail.Contracts.IOutletReportingContract_v1" />
<endpoint address="mex" binding="mexHttpsBinding" name="IMetadataExchange" contract="IMetadataExchange" />
</service>
<service name="Company.Services.Ticketing.Retail.OutletService_v2" behaviorConfiguration="Public">
<endpoint binding="wsHttpBinding" bindingConfiguration="Standard" contract="Company.Services.Ticketing.Retail.Contracts.IOutletReportingContract_v2" />
<endpoint address="mex" binding="mexHttpsBinding" name="IMetadataExchange" contract="IMetadataExchange" />
</service>
</services>

Related

Multiple contracts in one WCF service_But error for calling the second contract

I have multiple contracts in one WCF:
namespace SysLap.Services.Web.DataExtractor
{
[ServiceContract]
public interface IServiceDataExtractor
{
[OperationContract]
[WebGet]
List<User> GetAllUsers(/*CommonParams commonParams*/);
}
[ServiceContract]
public interface IScopesExtract
{
[OperationContract]
[WebGet]
List<SyScope> GetAllScopes();
}
}
and the Web.config is well configured:
<endpoint address="rest" behaviorConfiguration="restBehavior"
binding="webHttpBinding" contract="SysLap.Services.Web.DataExtractor.IServiceDataExtractor" />
<endpoint address="rest" behaviorConfiguration="restBehavior"
binding="webHttpBinding" contract="SysLap.Services.Web.DataExtractor.IScopesExtract" />
</service>
For the service GetAllUsers, it is worked very good. But for the service GetAllScopes, when i test it with SOAP UI, i am getting this error:
<p class="heading1">Request Error</p>
<p>The server encountered an error processing the request. The exception message is 'Multiple filters matched.'.
See server logs for more details. The exception stack trace is: </p>
<p> at System.ServiceModel.Dispatcher.EndpointDispatcherTable.LookupInCache(Message message, Boolean&
addressMatched)
at System.ServiceModel.Dispatcher.EndpointDispatcherTable.Lookup(Message message, Boolean&
addressMatched)
at System.ServiceModel.Dispatcher.ChannelHandler.GetDatagramChannel(Message message, EndpointDispatcher&
endpoint, Boolean& addressMatched)
at System.ServiceModel.Dispatcher.ChannelHandler.EnsureChannelAndEndpoint(RequestContext request)
at System.ServiceModel.Dispatcher.ChannelHandler.TryRetrievingInstanceContextCore(RequestContext request)
</p>
How can I fix it?
Thanks
You basically just need two separate endpoint address.
Change the config and give unique address, for example:
<endpoint address="DataExtractor" behaviorConfiguration="restBehavior" binding="webHttpBinding" contract="SysLap.Services.Web.DataExtractor.IServiceDataExtractor" />
<endpoint address="ScopesExtractor" behaviorConfiguration="restBehavior" binding="webHttpBinding" contract="SysLap.Services.Web.DataExtractor.IScopesExtract" />
When we use the WCF project template to create WCF service, normally there is only one service host in Service.svc(Markup).
<%# ServiceHost Language="C#" Debug="true" Service="WcfService3.Service1" CodeBehind="Service1.svc.cs" %>
It means that we could have multiple service contracts, but we merely can have one service(service implementation class).
Under this circumstance, hosting multiple service contracts in one project is valid.
public class Service1 : IService1,IService2
Back to your problem, the error mainly indicates that our services have the same relative address, this does not comply with the WCF addressing specification.
As Selim Yıldız said, we need two separate endpoint address.
<services>
<service name="WcfService3.Service1">
<endpoint address="a" binding="webHttpBinding" contract="WcfService3.IService1" behaviorConfiguration="rest"></endpoint>
<endpoint address="b" binding="webHttpBinding" contract="WcfService3.IService2" behaviorConfiguration="rest"></endpoint>
</service>
</services>
The service Url will be,
http://xxxx:xx/service1.svc/a/GetAllUsers
http://xxxx:xx/service1.svc/b/GetAllScopes
Feel free to let me know If there is anything I can help with.

One WCF service, multiple endpoints, different context per endpoint

I'm writing a multi-tenant WCF application. I've got one "general" service class that is responsible for executing some business logic. I'd like to configure WCF with Autofac in this way that each endpoint will receive different configuration params using custom configuration section e.g.:
<system.serviceModel>
<services>
<service name="MyApiService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:80000" />
</baseAddresses>
</host>
<endpoint name="Tenant1" address="tenant1" binding="basicHttpBinding" contract="IMyApiService" />
<endpoint name="Tenant2" address="tenant2" binding="basicHttpBinding" contract="IMyApiService" />
</service>
</services>
</system.serviceModel>
<apiConfigurationSection>
<service name="Tenant1" wcfServiceName="MyApiService" param1="value1" param2="value2" />
<service name="Tenant2" wcfServiceName="MyApiService" param1="value3" param2="value4" />
</apiConfigurationSection>
I'd like parameters param1 and param to be injected as a contex when matching service (by URL) is called.
Could you suggest me any solution how to do this?

WCF Discovery to search server with net.tcp://0.0.0.0:8888 address

I am trying to find my servers with the help of WCF Discovery protocol.
Everything is nice when I specify explicit address for server, for example: net.tcp://192.168.36.18:8888.
But when I specify net.tcp://0.0.0.0:8888 address on the server to listen all interfaces I receive net.tcp://0.0.0.0:8888 on the client. Certainly, I can't use this address to connect to the server.
Physically responce for wcf discovery request is coming from real servers addresses: 192.168.36.100, 192.168.36.239 and 192.168.36.61. I can see it by Wireshark. But I can't get this adresses from FindResponce class.
Is there a way to get physical address if server was configured to listen all interfaces by WCF discovery?
Code on the client:
var discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
var findResponce = discoveryClient.Find(new FindCriteria(typeof(IRadioService)));
discoveryClient.Close();
Code on the server:
var serviceHost = new ServiceHost(new RadioServer());
serviceHost.Open();
Config on the server:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="RadioServer">
<serviceDiscovery />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="RadioServer" name="Server.RadioServer">
<endpoint address="RS" binding="netTcpBinding" contract="Common.IRadioService" />
<endpoint name="udpDiscovery" kind="udpDiscoveryEndpoint" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://0.0.0.0:8888/" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>

getting error message related to basicHttpBinding even though I'm using wsHttpBinding

I am trying to expose a WCF service at a wsHttpBinding endpoint and it gives me the following error message :
Contract requires Session, but Binding
'BasicHttpBinding' doesn't support it
or isn't configured properly to
support it.
Here is the interface :
[ServiceContract(Namespace="http://server.com/orderservices/",SessionMode=SessionMode.Required)]
public interface IOrderService
{
[OperationContract(IsInitiating=true,IsTerminating=false)]
string GetOrderNumber();
[OperationContract(IsInitiating = false, IsTerminating = true)]
void CreateOrder(string orderXML);
}
Here is my web.config file (the service is hosted in IIS 7 ) :
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="longTimeoutBinding"
receiveTimeout="00:10:00" sendTimeout="00:10:00">
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="eMidWare.OrderService">
<host>
<baseAddresses>
<add baseAddress = "http://localhost/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<endpoint
address=""
binding="wsHttpBinding" bindingConfiguration="longTimeoutBinding"
contract="eMidWare.IPricingDataService">
</endpoint>
<endpoint
address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Hmmm.... check your service contract - it's a IOrderService
[ServiceContract(Namespace="http://server.com/orderservices/",SessionMode=SessionMode.Required)]
public interface IOrderService
{
}
but in your config, you're setting up an endpoint for eMidWare.IPricingDataService
<endpoint
address=""
binding="wsHttpBinding" bindingConfiguration="longTimeoutBinding"
contract="eMidWare.IPricingDataService">
Therefore, I believe, .NET / WCF 4 will kick in a default endpoint, which is of basicHttpBinding for the http:// scheme by default....
If you had posted your service interface I could have said with certainty but I believe you have something like this on your service interface:
[ServiceContract(SessionMode = SessionMode.Required)]
This would require session and BasicHttpBinding does not support it. You need to use wsHttpBinding if you need to have sessions.

Expose webHttpBinding endpoint in a WCF service

I created a WCF service and exposed three endpoints which are basicHttpBinding, wsHttpBinding and webHttpBinding. This is a test service for my experiments with WCF. But, whenever I add service reference using the .svc file, I only get two (basic and ws) endpoints. There doesn't seem to be a third (webHttpBidning) endpoint being exposed for some reason.
To reproduce this issue, create a WCF application project, delete the Service1 service, add new item > WCF service named TestService, and change the config file to the following :
<system.serviceModel>
<services>
<service name="WcfTestService.TestService" behaviorConfiguration="TestServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost/WcfTestService/TestService.svc"/>
</baseAddresses>
</host>
<endpoint address="basic"
binding="basicHttpBinding"
contract="WcfTestService.ITestService" />
<endpoint address="ws"
binding="wsHttpBinding"
contract="WcfTestService.ITestService" />
<endpoint address="web"
binding="webHttpBinding"
contract="WcfTestService.ITestService" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="TestServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
Here is the code for ITestService.cs:
[ServiceContract]
public interface ITestService
{
[OperationContract]
[WebInvoke]
Boolean ValidateUser(User user);
}
[DataContract]
public class User
{
[DataMember(Name = "Name")]
public String UserName { get; set; }
[DataMember]
public String Password { get; set; }
}
and for TestService.svc
public class TestService : ITestService
{
public bool ValidateUser(User user)
{
if (user.UserName == "User" && user.Password == "123")
{
return true;
}
return false;
}
}
I tried different combination of WebInvoke parameters and WebGet parameters, but failed.
Can anyone tell me why the third endpoint is not showing up in the WSDL file?
#decyclone: I have successfully exposed webHttpBindings without any issue. But I found some interesting thing when it get exposed and when it not!
I can see web binding getting exposed in Wcf Test Client.
Here are my configurations
<services>
<service behaviorConfiguration="TestWeb.Service2Behavior" name="TestWeb.Service2">
<endpoint address="" binding="wsHttpBinding" contract="TestWeb.Service2">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="web" binding="webHttpBinding" contract="TestWeb.Service2">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
Point to note here is, its working fine using VS2008 with Framework 3.5, VS2010 with Framework 3.5, when I use VS2010 and Framework 4.0 then I can't see WebHttpBinding getting exposed in WCF Test Client, however I can use that binidng to do http post in all cases.
I assume that in Framework 4.0 its not visible by default, even I try enable endpointDiscovery but still no luck!
I have covered this behaviour in my post
Your "web" endpoint will be exposed as a JSON endpoint. It is not compatible with WSDL.
WebHttpBinding is in System.ServiceModel.Web. If you are using vs2010, go to properties of your project, check target framework. By default it points to .Net Framework 4 Client Profile. It should point to .Net Framework 4, then you can find the System.ServiceModel.Web when you will go to Add reference
#decyclone: One way that a javascript client can learn the available methods on a webHttpBinding is to download a WCF javascript proxy with HTML script tags pointing to your endpoint followed by "/js": <script src="http://localhost/WcfTestService/TestService.svc/web/js"></script>

Categories

Resources