I am trying to get the service from a website ,so i connect to the webService like this :
BasicHttpBinding binding = new BasicHttpBinding();
EndpointAddress address = new EndpointAddress(domainAddress+"/services/reportSRC.svc");
ChannelFactory<IReportSRC> factory = new ChannelFactory<IReportSRC>(binding, address);
IReportSRC channel = factory.CreateChannel();
So but sometimes the service is not available .how can i check this ability ?i mean if the service is available i connect to it otherwise show the error the service is not available
Suppose i have a list that contains several services and a state ,if the service is available the state is true otherwise is false.
you can always use a try-catch block and call the method for testing purpose of your choice.
try
{
serviceClient.AnyMethod();
}
catch
{
//Service not available
}
Related
I want to develop a WCF service to support multiple contracts. I managed to make this work by following the instruction from this post on Stackoverflow.
So basically create one service(FooBarService) to implement multiple contracts(IFooService, IBarService).
string serviceAddress = "net.tcp://localhost:8088/FooBarService";
ServiceHost selfServiceHost = new ServiceHost(typeof(FooBarService));
// The endpoints need to share this binding.
var binding = new NetTcpBinding();
selfServiceHost.AddServiceEndpoint(typeof(IFooService), binding, serviceAddress);
selfServiceHost.AddServiceEndpoint(typeof(IBarService), binding, serviceAddress);
But the challenging thing is that I want to also make this service discoverable using WCF Discovery in order to decouple client and service from endpoint binding.
In the Service side, I did something like this:
var discoveryBehavior = new ServiceDiscoveryBehavior();
discoveryBehavior.AnnouncementEndpoints.Add(new AnnouncementEndpoint(new NetTcpBinding(SecurityMode.None), new EndpointAddress("net.tcp://localhost:8001/Announcement")));
_serviceHost.Description.Behaviors.Add(discoveryBehavior);
_serviceHost.AddServiceEndpoint(new UdpDiscoveryEndpoint());
It seems that the service can work.
But on one of client that want to only use contract IFooService, I always got the following error when I try to discover it.
Unable to discover the endpoint for contract.IFooService. Either no service exists or it does not support discovery.
Do you think if it is possible to achieve discoverable multiple contracts in one service in this case?
If YES, how can I do that based on the code i have right now?.
Thanks.
I would think it would be possible. Try doing the simplest thing first to see if that works:
string serviceAddress = "net.tcp://localhost:8088/FooBarService";
ServiceHost selfServiceHost = new ServiceHost(typeof(FooBarService));
// The endpoints need to share this binding.
var binding = new NetTcpBinding();
selfServiceHost.AddServiceEndpoint(typeof(IFooService), binding, serviceAddress);
selfServiceHost.AddServiceEndpoint(typeof(IBarService), binding, serviceAddress);
// Add ServiceDiscoveryBehavior
selfServiceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior());
// Add a UdpDiscoveryEndpoint
selfServiceHost.AddServiceEndpoint(new UdpDiscoveryEndpoint());
Client:
static EndpointAddress FindCalculatorServiceAddress()
{
// Create DiscoveryClient
DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
// Find ICalculatorService endpoints
FindResponse findResponse = discoveryClient.Find(new FindCriteria(typeof(IFooService)));
if (findResponse.Endpoints.Count > 0)
{
return findResponse.Endpoints[0].Address;
}
else
{
return null;
}
}
Also make sure that you can create clients with the two different contracts and call the services manually.
I'm in a situation where I want to use WCF to expose two different interfaces:
Internal (IPC communication)
External (Http REST)
The external interface shouldn't be able to see or use the internal interface so what I was thinking about were to host the two services on different ports e.g. (8000 for internal and 8001 for external) and then block all external communication on port 8000.
Moreover, I tried fiddling around with using named pipes for IPC communication, and I ran into an issue. If the unexpected situation occurs, that the service crashes or goes offline the client would also have to be restarted to be able to establish the communication with the service via the named pipes. Is this normal behavior and can it be avoided?
I have the following code so far:
// Service Host
var host = new ServiceHost(serviceContract, new Uri(_address));
host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
var behaviour = host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
behaviour.InstanceContextMode = InstanceContextMode.Single;
// Local Endpoint
host.AddServiceEndpoint(typeof(ILocalServiceContract), new BasicHttpBinding(), "Local");
host.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
// External Endpoint
var webHttpBidning = new WebHttpBinding { TransferMode = TransferMode.Streamed };
var externalEndPoint = host.AddServiceEndpoint(typeof(IExternalServiceContract), webHttpBidning, "External");
externalEndPoint.Behaviors.Add(new WebHttpBehavior());
They are currently both hosted on the same port which I want to avoid, I'm fairly new to WCF and I could really use some guidance for best practice and what I'm doing wrong. As mentioned earlier the 'BasicHttpBinding' could maybe be replaced with a named pipe if my issue can be resolved.
Looking forward to hear to the experts and if you need any clearification feel free to ask :)
I solved the issue with the following code on server. On the clients which communicate with the server via named pipes, I used "WcfClientProxyGenerator" library to generate fault tolerant client proxies.
_namedPipeAddress = "net.pipe://localhost/";
_httpAddress = "http://localhost:8000";
var host = new ServiceHost(serviceContract, new Uri(_namedPipeAddress), new Uri(_httpAddress));
host.Description.Behaviors.Add(new ServiceMetadataBehavior { });
var behaviour = host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
behaviour.InstanceContextMode = InstanceContextMode.Single;
behaviour.IncludeExceptionDetailInFaults = true;
// Local Endpoint
host.AddServiceEndpoint(typeof(ILocalServiceContract), new NetNamedPipeBinding(), "Local");
host.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexNamedPipeBinding(), "mex");
//// External Endpoint
var webHttpBidning = new WebHttpBinding { TransferMode = TransferMode.Streamed };
var externalEndPoint = host.AddServiceEndpoint(typeof(IExternalServiceContract), webHttpBidning, new Uri(_httpAddress));
externalEndPoint.Behaviors.Add(new WebHttpBehavior());
For further improvements to this solution feel free to comment :)
My application is a C# Windows service that consumes a WCF service. When the first "Expectation failed (417)" error occurs, I change both ServicePointManager.Expect100Continue and ServicePoint.Expect100Continue to false:
try
{
//ServicePointManager.Expect100Continue = false; // If uncomment all work
var svc = new ServiceClient();
svc.GetData(); // first error
}
catch (ProtocolException pex)
{
if (pex.Message.Contains("(417)"))
{
ServicePointManager.Expect100Continue = false;
var sp = ServicePointManager.FindServicePoint(new Uri(#"http://addr.to.service/service.svc"));
sp.Expect100Continue = false;
var svc = new ServiceClient();
svc.GetData(); // second same error
}
}
However, the second call to the service also fails. But if I set Expect100Continue to false before any connection, communication with the service works correctly.
Is this way correctly to handle Expect100Continue errors? I need the application adapts automatically without user action. What am I forgetting to do this work?
Most of the settings on ServicePointManager are treated as the default values applied on all NEW ServicePoints that are created after that point in the application's life. In the case where you change the setting after seeing the error, you are not actually changing anything on existing ServicePoint instances, including the instance associated with the connection used by WCF in this case.
In your Sample code you are calling ServicePointManager.FindServicePoint to try to find the correct ServicePoint. However, FindServicePoint has several overloads and it is easy to use that API incorrectly. For instance, FindServicePoint will try to take into account things http/https, the host you are connecting to, your proxy configuration, etc. If you are not providing the correct parameters to FindServicePoint, you can easily end up getting the wrong ServicePoint returned to you and your settings will not be applied to the ServicePoint you intended to change.
I would recommend that you use the FindServicePoint overload that takes an IWebProxy object to ensure that you get the right ServicePoint. In most cases, you should be able to pass in WebRequest.DefaultWebProxy as the IWebProxy object.
From the MSDN documentation of ServicePointManager.Expect100Continue,
Changing the value of this property does not affect existing ServicePoint objects. Only new ServicePoint objects created after the change are affected. Therefore changing the value on the existing WCF client will have no effect. You need to create a new WCF client, then call GetData()
I have UI where I have the user enter the Url where I can find the Exchange Web Service(EWS). My application uses EWS to get Free/Busy information but my configuration tool just needs to set it for the user.
For now I am just asking for the host name and building up the Url from there. For example they enter example.org as the host and I build https://example.org/EWS/Exchange.asmx from that.
I would like to add a test button to ensure the host they entered is reachable by the machine they are configuring. But I'm not sure how simple or complex I need to be to test the service.
Is there any noop or bind I can do to make sure I can establish communication with EWS?
Something like:
var serviceUri = new Uri(_textBoxEwsUrl.Text));
var exchangeService = new ExchangeService();
exchangeService.Url = serviceUri;
// what can I call here to test that I can talk to the exchangeService?
exchangeService.????
Bind to the inbox folder of the users mail address. Of course, you would need his credentials to this.
Any kind of operation that results in communication with server can be used as test. Simple binding to any folder or item will throw ServiceRequestException or some different type of exception if your url or credentials are incorrect.
Sample code:
try
{
var inbox = Folder.Bind(service, WellKnownFolderName.Inbox);
}
catch(ServiceRequestException e)
{
//handle exception in some way
}
I built a project as descripted in this URL:
http://msdn.microsoft.com/en-us/library/ms734784.aspx
I used the app.config version. But using the code-Version does not change anything (the timeout-error still occurs).
To create the ServiceHost I used the following code:
this.serviceHost = new ServiceHost(typeof(Calculator));
// Open the ServiceHostBase to create listeners and start
// listening for messages.
this.serviceHost.Open();
On the client side I used the following code:
ChannelFactory<ICalculator> factory = new ChannelFactory<ICalculator>("netTcp_ICalculator");
ICalculator communicationChannel = this.factory.CreateChannel();
string test = communicationChannel.GetData(5);
On the last line the program waits one minute, then I get a timeout:
This request operation sent to net.tcp://localhost:8008/Calculator did not
receive a reply within the configured timeout (00:01:00).
The time allotted to this operation may have been a portion
of a longer timeout. This may be because the service is still
processing the operation or because the service was unable to
send a reply message. Please consider increasing the operation
timeout (by casting the channel/proxy to IContextChannel and
setting the OperationTimeout property) and ensure that the service
is able to connect to the client.
The class Calculator and the interface exist. Besides this timeout I get no other error. I set a breakpoint at the GetData method, but the breakpoint was not hit.
I have tried to change the portnumber used for the client from 8008 to 8009, but let the endpoint for the server at 8008. I wanted to test if the client tries to reach the server. Then I get the error that the other side is not answering (EndpointNotFoundException).
When changing the client port back to 8008 I get the Timeout error again.
Is there anything wrong with my code?
How can I ensure that the server can reach the client?
Client and server are in the same test application.
Thank you for your help!
EDIT:
I have now deleted the app.config settings. And tried to build the server and client by using the sourcecode. To build the server was no problem. But building the client is a problem.
There is no way to call:
CalculatorClient cc = new CalculatorClient(myBinding, myEndpointAddress);
The compiler does not know CalculatorClient.
Can I use the following instead?
NetTcpBinding myBinding = new NetTcpBinding();
myBinding.Security.Mode = SecurityMode.None;
// Create the address string, or get it from configuration.
string tcpUri = "net.tcp://localhost:8008/Calculator";
// Create an endpoint address with the address.
EndpointAddress myEndpointAddress = new EndpointAddress(tcpUri);
ChannelFactory<ICalculator> factory = new ChannelFactory<ICalculator>(myBinding, myEndpointAddress);
factory.Open();
ICalculator communicationChannel = this.factory.CreateChannel();
string test = communicationChannel.GetData(5);
I get again an exception at the last line :(
SOLVED:
Ok, the problem is solved. I needed to call the WCF host initialization via an own thread:
hostThread = new Thread(this.createService);
hostThread.Start();
Now everything works fine!
Thanks for all your help!
You are not adding any endpoints to the service.
You did not include the part of the example code that adds the service endpoint:
Uri tcpUri = new Uri("net.tcp://localhost:8008/Calculator");
// Create the ServiceHost.
ServiceHost sh = new ServiceHost(typeof(Calculator), tcpUri);
// Create a binding that uses TCP and set the security mode to none.
NetTcpBinding b = new NetTcpBinding();
b.Security.Mode = SecurityMode.None;
// Add an endpoint to the service.
sh.AddServiceEndpoint(typeof(ICalculator), b, "");
// Open the service and wait for calls.
sh.Open();
Edit: Same goes for your client. You have to specify an endpoint addresses
// Create a channel factory.
NetTcpBinding b = new NetTcpBinding();
b.Security.Mode = SecurityMode.None;
Uri tcpUri = new Uri("net.tcp://localhost:8008/Calculator");
ChannelFactory<ICalculator> myChannelFactory = new ChannelFactory<ICalculator>(b,new EndpointAddress(tcpUri));
// Create a channel.
ICalculator calculator = myChannelFactory.CreateChannel();
Edit2: I can't currently test this code... Will give it a try tomorrow morning.
Are you using Windows 7?
If so, you likely need to run Visual Studio as an Administrator. UAC will not let you create the service endpoint unless you are a running as an administrator.