I am working on WCF application, starting simple HelloWorld service. I have develop simple WPF application to host services, i.e. start and stop service
when I try to test this service with url "http://localhost:8087/MyServices/HelloWorldService" on WCFTestClient, I am getting following error
Error: Cannot obtain Metadata from http://localhost:8087/MyServices/HelloWorldService If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address. For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange Error URI: http://localhost:8087/CreditUnionServices/HelloWorldService Metadata contains a reference that cannot be resolved: 'http://localhost:8087/CreditUnionServices/HelloWorldService'. <?xml version="1.0" encoding="utf-16"?><Fault xmlns="http://www.w3.org/2003/05/soap-envelope"><Code><Value>Sender</Value><Subcode><Value xmlns:a="http://schemas.xmlsoap.org/ws/2005/02/sc">a:BadContextToken</Value></Subcode></Code><Reason><Text xml:lang="en-GB">The message could not be processed. This is most likely because the action 'http://schemas.xmlsoap.org/ws/2004/09/transfer/Get' is incorrect or because the message contains an invalid or expired security context token or because there is a mismatch between bindings. The security context token would be invalid if the service aborted the channel due to inactivity. To prevent the service from aborting idle sessions prematurely increase the Receive timeout on the service endpoint's binding.</Text></Reason></Fault>HTTP GET Error URI: http://localhost:8087/CreditUnionServices/HelloWorldService There was an error downloading 'http://localhost:8087/CreditUnionServices/HelloWorldService'. The request failed with HTTP status 400: Bad Request.
app.config
<system.serviceModel>
<services>
<service name="App.Services.Managers.HelloWorldManager">
<endpoint address="HelloWorldService"
binding="wsHttpBinding"
contract="App.Services.Contracts.IHelloWorldService">
</endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8087/MyService"/>
</baseAddresses>
</host>
</service>
</services>
C# class to open and close service
public class ServicesHostManager
{
ServiceHost _helloWorldServicesHost = new ServiceHost(typeof(HelloWorldManager));
public void ProcessHelloWorldService(string _process)
{
if(!string.IsNullOrEmpty(_process))
{
try
{
if (_process.Equals("open_service"))
{
_helloWorldServicesHost.Open();
}
else if (_process.Equals("close_service"))
{
_helloWorldServicesHost.Close();
}
}
catch (Exception e)
{
System.Windows.MessageBox.Show(e.ToString());
}
}
}
The previous commenter was on the right track, you need to declare a mex endpoint. mex is what provides the MetaData.
Try the following config:
<system.serviceModel>
<services>
<service name="App.Services.Managers.HelloWorldManager" behaviorConfiguration="SimpleWcfServiceBehavior">
<endpoint address="HelloWorldService"
binding="wsHttpBinding"
contract="App.Services.Contracts.IHelloWorldService">
</endpoint>
<endpoint address="mex" binding="mexTcpBinding" bindingConfiguration="" contract="IMetadataExchange"></endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8087/MyService"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="SimpleWcfServiceBehavior">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<!-- 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="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
I have update code and is working now,
<system.serviceModel>
<services>
<service name="App.Services.Managers.HelloWorldManager" behaviorConfiguration="DefaultServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8087/MyService"/>
</baseAddresses>
</host>
<endpoint address="HelloWorldService" binding="wsHttpBinding" contract="App.Services.Contracts.IHelloWorldService"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DefaultServiceBehavior">
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
Related
I created a wcf service by creating a wcf application project using VS2013.
My service contract is IWCFService,and I have a implement of IWCFService called WCFService
[ServiceContract]
public interface IWCFService
{
[OperationContract]
void DoWork();
}
public class WCFService : IWCFService
{
public void DoWork()
{
//do something
}
}
my service config is below:
<system.serviceModel>
<services>
<service name="WcfService2.WCFService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration=""
contract="WcfService2.IWCFService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:5831/WCFService" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- 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="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
When i start my application i can add a service reference via url http://localhost:5831/WCFService.svc but when i try to add service reference via http://localhost:5831/WCFService noting was found.why the address i defined in web.config could not help?
<baseAddresses> will only work if your services are hosted in a self hosted environment.
Represents a collection of baseAddress elements, which are base
addresses for a service host in a self-hosted environment. If a base
address is present, endpoints can be configured with addresses
relative to the base address.
I have WCF service how run on 1 machine and simple comsole application client who run on another machine.
the server do something very simple: one method that return the value of 2 number that the client sent:
[ServiceContract]
public interface IMySampleWCFService
{
[OperationContract]
int Add(int num1, int num2);
[OperationContract]
void CreateDirectory(string directory);
[OperationContract]
string GetVendorToRun(string path);
}
public class MySampleWCFService : IMySampleWCFService
{
public int Add(int num1, int num2)
{
return num1 + num2;
}
}
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 name="WCFServiceHostingInWinService.MySampleWCFService">
<endpoint
name="ServiceHttpEndPoint"
address=""
binding="basicHttpBinding"
contract="WCFServiceHostingInWinService.IMySampleWCFService">
</endpoint>
<endpoint
name="ServiceMexEndPoint"
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://192.0.16.250:8733/MySampleWCFService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the value below to false before deployment -->
<serviceMetadata httpGetEnabled="True"/>
<!-- 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>
</behaviors>
</system.serviceModel>
</configuration>
What i want to do and find it hard to implement because i am a new developer is add Discovery to my WCF service, suppose i have several services that installed on several machines, what the client application is open i want to now which services is alive\running and all this data that i can received from Discovery.
I try to read several articles but as i mention didn't understand how to do it and I would love some help.
Using WCF Discovery is a bit convoluted and few people actually use it in my experience but it does work. This MSDN article has all the detail needed for adding Discovery to both the service & client configuration files.
The premise behind WCF Discovery is that you a expose a new discovery endpoint in similar way to the default MEX endpoint. The MEX endpoint allows the service to provide WSDL to clients. A WCF Discovery endpoint exposes a configured service to clients by means of UDP based responses to client UDP based requests. The overview link above provides much more detail.
Here is how your service configuration would look like:
<system.serviceModel>
<services>
<service name="WCFServiceHostingInWinService.MySampleWCFService">
<endpoint
name="ServiceHttpEndPoint"
address=""
binding="basicHttpBinding"
contract="WCFServiceHostingInWinService.IMySampleWCFService"
behaviorConfiguration="endpointDiscoveryBehavior">
</endpoint>
<endpoint
name="ServiceMexEndPoint"
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
<!-- Discovery Endpoint: -->
<endpoint kind="udpDiscoveryEndpoint" />
<host>
<baseAddresses>
<add baseAddress="http://192.0.16.250:8733/MySampleWCFService/" />
</baseAddresses>
</host>
</service>
<!-- Announcement Listener Configuration -->
<service name="AnnouncementListener">
<endpoint kind="udpAnnouncementEndpoint" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the value below to false before deployment -->
<serviceMetadata httpGetEnabled="True"/>
<!-- 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" />
<serviceDiscovery>
<announcementEndpoints>
<endpoint kind="udpAnnouncementEndpoint"/>
</announcementEndpoints>
</serviceDiscovery>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="endpointDiscoveryBehavior">
<endpointDiscovery enabled="true"/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
I think the most easy way to do this is to try to connect your client to addresses that you calculate at the runtime. For example:
static void Main(string[] args)
{
var addresses = new List<string>
{
#"http://192.168.1.1:8730/MySampleWCFService/",
#"http://localhost:8731/MySampleWCFService/",
#"http://localhost:8732/MySampleWCFService/",
#"http://localhost:8733/MySampleWCFService/",
};
foreach (var address in addresses)
{
var client = new MySampleWCFServiceClient(new BasicHttpBinding(), new EndpointAddress(address));
try
{
client.Open();
client.Add(0, 1);
Console.WriteLine("Connected to {0}", address);
}
catch (EndpointNotFoundException)
{
Console.WriteLine("Service at {0} is unreachable", address);
}
}
Console.ReadLine();
}
In my case I create a list with addresses but in your case you may build addresses with some predefined rules. For example you know that services use http binding with some name and port. Also you know that your cluster is in 192.0.16.xxx LAN so you may use formula:
address = "http://" + NextLanAddress() + ":" + port + "/" + serviceName + "/";
This really is bugging me for a couple of hours. I created the simplest WCF service using a TCP binding.
namespace WcfTcpService
{
public class TestTcpService : ITestTcpService
{
public string Hello(string name)
{
return "Hello, " + name + "!";
}
}
}
namespace WcfTcpService
{
[ServiceContract]
public interface ITestTcpService
{
[OperationContract]
string Hello(string name);
}
}
Web.config file has the following section:
<system.serviceModel>
<services>
<service name="WcfTcpService.TestTcpService" behaviorConfiguration="TestServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:808/WcfTcpService.TestTcpService" />
</baseAddresses>
</host>
<endpoint address="" binding="netTcpBinding" bindingConfiguration="tcpBinding" contract="WcfTcpService.ITestTcpService"></endpoint>
<endpoint address="mex" binding="mexTcpBinding" bindingConfiguration="" contract="IMetadataExchange"></endpoint>
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="tcpBinding" portSharingEnabled="true">
<security mode="None"></security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="TestServiceBehavior">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- 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="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<!--<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
<add binding="netTcpBinding" scheme="net.tcp" />
</protocolMapping>-->
<!--<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />-->
</system.serviceModel>
This service is hosted in IIS:
Now, when trying to add a reference to net.tcp://localhost:808/WcfTcpService.TestTcpService from a client application, I keep receiving the error:
The URI prefix is not recognized.
Metadata contains a reference that cannot be resolved: 'net.tcp://localhost/WcfTcpService.TestTcpService'.
The message could not be dispatched because the service at the endpoint address 'net.tcp://localhost/WcfTcpService.TestTcpService' is unavailable for the protocol of the address.
If the service is defined in the current solution, try building the solution and adding the service reference again.
The net.tcp service is running, I receive the same error with WcfTestClient.exe. and I can succesfully run http://localhost/WcfTcpService/TestTcpService.svc.
I've searched google but nothing came up.
Thanks!
EDIT:
The bindings screen of the 'Default Web site' looks like this btw:
When you create service that uses netTcpBinding and you want to Add service reference in Visual Studio you should use http address (httpGetEnabled) not actual tcp address the service listens on. So the solution was to set localhost/WcfTcpService/TestTcpService.svc as an url in Add service reference dialog.
I had same problem and I changed web.config as below:
<serviceHostingEnvironment multipleSiteBindingsEnabled="true">
<baseAddressPrefixFilters>
<add prefix="net.tcp://YourBaseUrl"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
Im trying to host to different service implementations of the same contract:
The reason is that need a dummy implementation for out-of-the-house testing.
Im trying to host both in the same WindowsService:
private ServiceHost _host;
private ServiceHost _dummy;
protected override void OnStart(string[] args)
{
_host = new ServiceHost(typeof(Service));
_host.Open();
//trying to avoid the app.config beeing used - because its already been hoste by _host
_dummy = new ServiceHost(typeof(TestDummyService));
_dummy.Description.Endpoints.Clear();
_dummy.AddServiceEndpoint(typeof(IService),
new WebHttpBinding(),
#"<link>/Dummy.svc/");
_dummy.ChannelDispatchers.Clear();
_dummy.Open();
}
This is the config file:
<system.serviceModel>
<services>
<service name="namespace.Service">
<host>
<baseAddresses>
<add baseAddress="<link>/Service.svc"/>
</baseAddresses>
</host>
<endpoint address=""
binding="webHttpBinding"
contract="namespace.IService"
behaviorConfiguration="web" />
<endpoint address="/mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors >
<behavior>
<serviceMetadata httpGetEnabled="true"
httpGetUrl="<link>/Service.svc/About" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name ="web">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
The ChannelDispatcher at /Service.svc/About with Contracts ‘IHttpGetHelpPageAndMetadataContract’ is unable to open.
any help is appreciated.
Update 1
My goal is to have 2 different implementations of the same contract (IService) hosted in one WindowsService.
I would also like to configure both of them in the config file.
Well i would like to know what's the business scenario. All I guess is, the client should not know the implementation, its just the URL of the service would indicate (or route) to the implementation.
Kindly clarify.
Refer to this existing post and let
me know if it makes sense.
The above post is hinting the implementation, refer to this post for deployment details.
so i found out, that even thow the testdummy service was added programatic, it still got the service metadatabehavior.
My solution was to not make the dehavior default - given it at name:
app.config:
<service name="namespace.Service" behaviorConfiguration="someName">
//.. later:
<behavior name="someName">
<serviceMetadata httpGetEnabled="true"
httpGetUrl="<link>/Service.svc/About" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
The rest of the code, statyed the same
Can't you add another endpoint and fill in the adress with a distinct name:
<endpoint address="/SecondService"
binding="webHttpBinding2"
contract="namespace.IService"
/>
Url becomes /Service.svc/SecondService
I am getting the following error when trying to use the WCF Test Client to hit my new web service. What is weird is every once in awhile it will execute once then start popping this error.
Failed to invoke the service. Possible causes: The service is offline or inaccessible; the client-side configuration does not match the proxy; the existing proxy is invalid. Refer to the stack trace for more detail. You can try to recover by starting a new proxy, restoring to default configuration, or refreshing the service.
My code (interface):
[ServiceContract(Namespace = "http://rivworks.com/Services/2010/04/19")]
public interface ISync
{
[OperationContract]
bool Execute(long ClientID);
}
My code (class):
public class Sync : ISync
{
#region ISync Members
bool ISync.Execute(long ClientID)
{
return model.Product(ClientID);
}
#endregion
}
My config (EDIT - posted entire serviceModel section):
<system.serviceModel>
<diagnostics performanceCounters="Default">
<messageLogging logMalformedMessages="true" logMessagesAtServiceLevel="true"
logMessagesAtTransportLevel="true" />
</diagnostics>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" />
<behaviors>
<endpointBehaviors>
<behavior name="JsonpServiceBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="SimpleServiceBehavior">
<serviceMetadata httpGetEnabled="True" policyVersion="Policy15"/>
</behavior>
<behavior name="RivWorks.Web.Service.ServiceBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- 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>
</behaviors>
<services>
<service name="RivWorks.Web.Service.NegotiateService" behaviorConfiguration="SimpleServiceBehavior">
<endpoint address=""
binding="customBinding"
bindingConfiguration="jsonpBinding"
behaviorConfiguration="JsonpServiceBehavior"
contract="RivWorks.Web.Service.NegotiateService" />
<!--<host>
<baseAddresses>
<add baseAddress="http://kab.rivworks.com/services"/>
</baseAddresses>
</host>
<endpoint address=""
binding="wsHttpBinding"
contract="RivWorks.Web.Service.NegotiateService" />-->
<endpoint address="mex"
binding="mexHttpBinding"
contract="RivWorks.Web.Service.NegotiateService" />
</service>
<service name="RivWorks.Web.Service.Sync" behaviorConfiguration="RivWorks.Web.Service.ServiceBehavior">
<endpoint address="" binding="wsHttpBinding" contract="RivWorks.Web.Service.ISync" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<extensions>
<bindingElementExtensions>
<add name="jsonpMessageEncoding" type="RivWorks.Web.Service.JSONPBindingExtension, RivWorks.Web.Service, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</bindingElementExtensions>
</extensions>
<bindings>
<customBinding>
<binding name="jsonpBinding" >
<jsonpMessageEncoding />
<httpTransport manualAddressing="true"/>
</binding>
</customBinding>
</bindings>
</system.serviceModel>
2 questions:
What am I missing that causes this error?
How can I increase the time out for the service?
TIA!
Found the problem(s)...
Had an error inside the web service that was not handled.
The test app does not do an ABORT when it sees an error. Instead, it is left unhandled (and unreported) AND the channel is now locked because of the error.
Putting a try/catch around the inside method makes it so I can log the error and the test app does not lock up.