Silverlight client consuming WCF service - c#

Please bear with me as I am new to WCF services/ Windows services. I've created a WCF service hosted in a Windows service. I want to consume that WCF service in a Silverlight in-browser application over TCP. Below is the code fragment in Silverlight to access WCF service:
var messageEncoding = new BinaryMessageEncodingBindingElement();
var tcpTransport = new TcpTransportBindingElement();
var binding = new CustomBinding(messageEncoding, tcpTransport);
// Create a channel factory for the service endpoint configured with the custom binding.
var cf = new ChannelFactory<ICalcService>(binding, new EndpointAddress("net.tcp://192.168.2.104:4508"));
// Open the channel.
ICalcService channel = cf.CreateChannel();
// Invoke the method asynchronously.
channel.BeginAdd(9, 5, AddCallback, channel);
private void AddCallback(IAsyncResult asyncResult)
{
try
{
double endAdd = ((ICalcService) asyncResult.AsyncState).EndAdd(asyncResult);
}
catch (Exception exception)
{
throw exception;
}
}
The code works fine sometimes but often it throws an infamous System.ServiceModel.CommunicationException with the following message for some reasons:
Could not connect to net.tcp://192.168.2.104:4508/. The connection attempt lasted for a time span of 00:00:00.1010058. TCP error code 10013: An attempt was made to access a socket in a way forbidden by its access permissions.. This could be due to attempting to access a service in a cross-domain way while the service is not configured for cross-domain access. You may need to contact the owner of the service to expose a sockets cross-domain policy over HTTP and host the service in the allowed sockets port range 4502-4534.
The innerException of type System.Net.Sockets.SocketException says
An attempt was made to access a socket in a way forbidden by its access permissions.
What are the possible reasons behind this exceptions? Based on what I investigated so far, I could find only one reason: Improper ClientAccessPolicy.xml. What may be the other reasons? If you have any useful resources, please provide me the same. One more question, if I want to make Windows service hosted WCF service to get consumed by other machines on LAN, what settings do I have to make? E.g. firewall settings? My code cannot access WCF service on other machine. It throws the same exception I mentioned above. Any ideas about how to get rid of this exception?

Problem sorted..!! I had to do following things:
1) Specified SecurityMode.None while creating NetTcpBinding in Windows service.
2) Created an Inbound Rule in Windows Firewall With Advanced Security to allow TCP traffic on the port I specified in the end point address.

Related

Call Azure Service Fabric from outside

I'm playing with Azure Service Fabric and a console app. I simply want my console app to connect to the cluster and do some stuff.
The console app try to resolve the service address with the following:
static void Main(string[] args)
{
ServicePartitionResolver resolver = null;
try
{
resolver = new ServicePartitionResolver(
new string[] {
"localhost:19000",
"localhost:19001"
});
Uri serviceUri = new Uri("fabric:/StatefullServiceTEST/MyStatefulService");
ResolvedServicePartition partition = resolver.ResolveAsync(serviceUri, new ServicePartitionKey(), CancellationToken.None).GetAwaiter().GetResult();
}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex.Message}");
}
Console.WriteLine();
Console.Write("Press any key to exit...");
Console.ReadKey();
}
My problem is that resolver.ResolveAsync throws an exception that doesn't seem to have any connection with Service Fabric:
Unable to cast COM object of type 'System.__ComObject' to interface
type 'IFabricApplicationManagementClient10'. This operation failed
because the QueryInterface call on the COM component for the interface
with IID '{67001225-D106-41AE-8BD4-5A0A119C5C01}' failed due to the
following error: No such interface supported (Exception from HRESULT:
0x80004002 (E_NOINTERFACE)).
Any ideas on this?
UPDATE
I was not so clear explaining my problem and what I want to achive.
I'm playing with Azure Service Fabric (both stateless and stateful services): my question is: what's the best way to call a micro service hosted in Azure Service Fabric?
Regards,
Attilio
You have to create a public facing service (such as Asp.net Core Web Api) which will expose the functionality of your service inside service fabric to outside world (outside the service fabric cluster). FabricClient approach is to be utilzied for calling services from within the service fabric cluster and not outside.
From your Asp.net Core service you will use the FabricClient to access the service hosted, so in general your asp.net core app act as reverse proxy to expose the functionality of actual service.
You can't use ServicePartitionResolver, it is a reliable service feature and must be called from within a service running in your cluster.
I couldn't understand clearly what you want.
If you want to manage the service and get details about it, like query running instances or replicas, add or remove instances, and so on, Use the Fabric Client, below is a quick snippet, check details here and here:
`
using System.Fabric;
using System.Security.Cryptography.X509Certificates;
string clientCertThumb = "71DE04467C9ED0544D021098BCD44C71E183414E";
string serverCertThumb = "A8136758F4AB8962AF2BF3F27921BE1DF67F4326";
string CommonName = "www.clustername.westus.azure.com";
string connection = "clustername.westus.cloudapp.azure.com:19000";
var xc = GetCredentials(clientCertThumb, serverCertThumb, CommonName);
var fc = new FabricClient(xc, connection);`
or,
If you want to communicate to a running service, like an API, you should use a Reverse Proxy to resolve your services via URL, like the below snippet, more details here:
http://mycluster.eastus.cloudapp.azure.com:19081/MyApp/MyService
You cannot access service in an ASF cluster from the outside using the ServicePartitionResolver.
You have to have a public facing endpoint on your cluster, like a stateless service acting as a web api for example.
From the docs:
Services connecting to each other inside a cluster generally can directly access the endpoints of other services because the nodes in a cluster are on the same local network. In some environments, however, a cluster may be behind a load balancer that routes external ingress traffic through a limited set of ports. In these cases, services can still communicate with each other and resolve addresses using the Naming Service, but extra steps must be taken to allow external clients to connect to services.
A Service Fabric cluster in Azure is placed behind an Azure Load Balancer. All external traffic to the cluster must pass through the load balancer. The load balancer will automatically forward traffic inbound on a given port to a random node that has the same port open. The Azure Load Balancer only knows about ports open on the nodes, it does not know about ports open by individual services.
So, unless your console app is hosted in the cluster as a guest executable, you have some more work to do.

Service Fabric FabricConnectionDeniedException when calling Stateless Service via Remoting

I've got a standalone on-premise Service Fabric Cluster that is secured using Windows Authentication.
In this application I have a ASP.NET Core WebApi Stateless service that tries to communicate with another stateless service via the remoting. Unfortunately I'm getting the following error when the WebApi service tries to RPC to the stateless service:
System.AggregateException: One or more errors occurred. ---> System.Fabric.FabricConnectionDeniedException: Not authorized to connect ---> System.Runtime.InteropServices.COMException: Exception from HRESULT: 0x80071C43
at Microsoft.ServiceFabric.FabricTransport.NativeServiceCommunication.IFabricServiceCommunicationClient2.EndRequest(IFabricAsyncOperationContext context)
at Microsoft.ServiceFabric.FabricTransport.Client.FabricTransportClient.EndRequest(IFabricAsyncOperationContext context)
at System.Fabric.Interop.AsyncCallOutAdapter2`1.Finish(IFabricAsyncOperationContext context, Boolean expectedCompletedSynchronously)
--- End of inner exception stack trace --
Futhermore, I can confirm that
When deploying this same application to a "development cluster" (i.e. either my local machine or another a remote Service Fabric cluster running all it's Nodes on one machine), I don't get the error - hence potentially an issue with the AD accounts I've used to setup my multi-machine cluster (I'm using a machine group account).
When creating the Client Proxy, I do setup the Security Credentials to use windows authentication - i.e.
var transportSettings = new FabricTransportRemotingSettings
{
SecurityCredentials = new WindowsCredentials()
};
Func<IServiceRemotingCallbackClient, IServiceRemotingClientFactory> clientProxyFactory = c => new FabricTransportServiceRemotingClientFactory(transportSettings);
var serviceProxyFactory = new ServiceProxyFactory(clientProxyFactory);
TService clientProxy = serviceProxyFactory.CreateServiceProxy<TService>(uri);
return clientProxy;
In the above code, if I instead use:
SecurityCredentials = new NoneSecurityCredentials() then I get a similar FabricConnectionDeniedException but the message is slightly different saying that the Client is not authorised to connect. This makes sense - but again, potentially indicates that there is an issue with my transport settings...

Azure connection failed because connected host has failed to respond ip:443

So I implemented an interface to communicate with a rest web service using the HttpClient class to make requests.
The code works perfectly locally, but when I deploy to Azure my application can't fire the request, it crashes on this line:
using (var response = await HttpClient.PostAsync(uri, content)) { ... }
// uri = https://api-rest.zenvia360.com.br/services/send-sms
The exact exception message is this:
A connection attempt failed because the connected party did not properly
respond after a period of time, or established connection failed because
connected host has failed to respond 200.203.125.26:443
The web service provider states that "if you use firewall or proxy you must add and exception for our IPs. For HTTPS, use port 443:
200.203.125.24
200.203.125.25
200.203.125.26 (the ip of the exception message)
200.203.125.27
200.203.125.28
200.203.125.29"
I looked everywhere in Azure looking for a firewall or something and I got nothing. Also this exception message is pretty cryptc. I tested the same code with another url (fired a post to www.gooogle.com) and it worked.
Any ideas?
The problem turned out to be on the web service side. The service I'm using blocks international requests by default. I asked them to whitelist the azure outbound IPs and now it works.

WCF with visual studio 2012

I am new WCF programming, I did followed series of Getting Started tutorials from following link
http://msdn.microsoft.com/en-us/library/ms734712.aspx
I have hosted service in console application but when I tried to create a client and tried to add service reference I got the following exceptions.
There was an error downloading
'http: localhost:8000/GettingStarted/mex/_vti_bin/ListData.svc/$metadata'.
The request failed with HTTP status 405: Method Not Allowed. Metadata
contains a reference that cannot be resolved:
'http: localhost:8000/GettingStarted/mex'. There was no endpoint
listening at http: localhost:8000/GettingStarted/mex that could
accept the message. This is often caused by an incorrect address or
SOAP action. See InnerException, if present, for more details. The
remote server returned an error: (404) Not Found. If the service is
defined in the current solution, try building the solution and adding
the service reference again.
code of hosting application
class Program
{
static void Main(string[] args)
{
// Step 1 Create a URI to serve as the base address.
Uri baseAddress =
new Uri("http://localhost:8000/GettingStarted/");
// Step 2 Create a ServiceHost instance
ServiceHost selfHost =
new ServiceHost(typeof(CalculatorService), baseAddress);
try
{
// Step 3 Add a service endpoint.
selfHost.AddServiceEndpoint(typeof(ICalculator),
new WSHttpBinding(),
"CalculatorService");
// Step 4 Enable metadata exchange.
var smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);
// Step 5 Start the service.
selfHost.Open();
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate.");
Console.WriteLine();
Console.ReadLine();
// Close the ServiceHostBase to shutdown.
selfHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("exception: {0}", ce.Message);
selfHost.Abort();
}
}
}
Now I am unable to figure out what the problem is. I am using visual studio 2012 and .net platform 4.5.
I had a similar issue as well, messing with this. Yes you seem to have followed the tutorial correctly, but if you want to connect to it and consume as a service (as in make a service reference) you must also add in the MEX service enpoint. Add this line after your selfhost.Description.Behaviors.Add(smb):
selfhost.AddServiceEndpoint(
typeof(IMetadataExchange),
MetadataExchangeBindings.CreateMexHttpBinding(),
"http://localhost:8000/GettingStarted/mex");
That should enable you to connect via "Add Service Reference". Also, I have found depending on your system, you may need to run VS as admin to allow for connection to network (in case you accidentally told it no in the past).
Judging from the error message it seems that there is no service listening at the specified port. You need to have the console application which hosts the service running when you are trying to add a service reference to it.
Apparently, the service is not running which means there is no endpoint listening at the URL you are using to create the service reference.
You can host the service in IIS, or keep the console application running as Damir mentioned above.
Make sure your server is running when you are trying to access it. Also check the configuration on the server and make sure your client's endpoint matches the server's endpoint. Make sure you're using the same binding as well, while you're at it.
Make sure the server is listening and the server's firewall isn't blocking you.
If you made a change to your WCF service don't forget to regenerate the service reference for your client application.
Are you sure you have defined a MEX endpoint? This is what provides metadata information about your service, so that studio can generate a client proxy.
In the tutorial you linked to, it is this bit:
// Step 4 Enable metadata exchange.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);
If you are hosting the web service in IIS, check in web.config(under behaviours section)
httpsGetEnabled is set to True
I ran into a similar problem today. However, for me it wasn't needed for me to explicitly add the Endpoints, as #iMortalitySX already said.
I had a different reason for failing: I was binding to http://0.0.0.0, thinking the listen IP doesn't matter. Indeed, via SoapUI I was able to connect and to use the Service. But when trying to discover the service in another Visual Studio project, the discovery would fail, as VS would get the initial response, but then follow up links that contained http://0.0.0.0 and then fail.
So changing http://0.0.0.0 into the correct IP of my machine fixed my problem.
Try put the uri address in Your browser. In my case I was able to see an ExceptionDetail.

WCF error "no endpoint listening" with named pipes

I'm using WCF with .NET 3.5 I am using named pipes but keep getting the error
There was no endpoint listening at
net.pipe://localhost/Test that could
accept the message. This is often
caused by an incorrect address or SOAP
action.
I followed the tutorial http://www.switchonthecode.com/tutorials/wcf-tutorial-basic-interprocess-communication but the problem remains. The endpoints on both the client and server are the same (I checked spelling etc). There is no config file for this project but the config is in the code.
EDIT: Code (client):
ChannelFactory<ITest> pipeFactory =
new ChannelFactory<ITest>(
new NetNamedPipeBinding(),
new EndpointAddress(
"net.pipe://localhost/test"));
ITest test= pipeFactory.CreateChannel();
test.doStuff();
SERVER:
serviceHost = new ServiceHost(typeof(Test), new Uri("net.pipe://localhost"));
serviceHost.AddServiceEndpoint(typeof(ITest), new NetNamedPipeBinding(), "test");
File.Create(#"C:\test.txt");
serviceHost.Open();
Thanks
On the server side don't include base addresses when you create the ServiceHost instance. Instead, provide the fully qualified endpoint address when you add the service endpoint:
serviceHost = new ServiceHost(typeof(Test));
serviceHost.AddServiceEndpoint(typeof(ITest), new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/test"));
File.Create(#"C:\\test.txt");
serviceHost.Open();
This could be:
You are running it as a windows service and the service is not running
You are running it as a console app and there is no console.readline, so it just exists
You are running client and server on two different machines so that localhost is not going to the machine with the service.
Another possibility to fix this root issue if you are getting an error that no net.pipe address can be found at your url (i.e. http://localhost:1234/MyService/etc/) is to make sure that the Net.Pipe Listener Adapter Windows Service is started. (I also started Net.Tcp Listener Adapter)
The service does not seem to be enabled or started in some scenarios especially when deploying out to a remote server that might not of had a lot of the development tools installed that actively use these services. Starting the service fixed the issue.

Categories