Mono WCF issue on OSX - c#

I've written a mono compatible application that works fine on a Windows machine and mostly works on my mac. The area that currently doesn't work is the layer that uses the WCF (ChannelFactory) to communicate between server and client.
The issue appears to be when I try and open the ChannelFactory on the Server, here is a code snippet:
string address = "21"; // added this for simplicity in conveying the problem...
string server_address = "net.tcp://192.168.1.122:4505/DeviceServer/";
string serviceAddress = string.Format(server_address, address);
ThreadedServiceHost<DeviceService, IDeviceContract> DeviceHost =
new ThreadedServiceHost<DeviceService, IDeviceContract>(serviceAddress, address, new NetTcpBinding());
EndpointAddress endPoint = new EndpointAddress(
new Uri(string.Format(serviceaddress, address) + address));
System.ServiceModel.Channels.Binding binding = new NetTcpBinding();
teeGlobal.ServerDeviceFactory = new ChannelFactory<IDeviceChannel>(binding, endPoint);
teeGlobal.ServerDeviceFactory.Open();
The issue is with the .Open() call - it just appears to hang on my mac. Creating the endpoint takes a lot longer to create than on my PC (about 3-4 seconds) but I can live with this if I can get the WCF layer to function.
Does anyone have any suggestions on how to progress with this issue?

The most recent stable release of Mono is 2.8.2 (http://www.go-mono.com/mono-downloads/download.html)
You really need to try with this version before doing anything else. The WCF stack in 2.6.x was more of a 'preview' than anything else, and only some common scenarios actually worked. 2.8 is much more complete.

Related

Could not establish secure channel for SSL/TLS with authority "......" but TLS is set in the code. Works fine on local machine but not in Production

I'm trying this code to reach an API but it doesn't work on PROD server and I don't know why. In local it works fine on my laptop.
/*ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;*/
_client = new HttpBinding<ThalentoWebservicePortType>(#Uri, System.ServiceModel.Channels.MessageVersion.Soap11, (binding, httpTransport, address, factory) =>
{
var basicAuthBehavior = new BasicAuthBehavior(UserName, Password);
factory.Endpoint.Behaviors.Add(basicAuthBehavior);
});
I'm working with .NET Framework 4.6.1
Thanks a lot for your help because I'm lost with this issue... :-)
Welcome to Stackoverflow!
Make sure the prod server (and client of course) is itself capable of TLS1.2 - some windows server versions had to get it via update, and given net461 I guess you work in a rather slow moving company similar to me. With 2016 it's enabled by default, but I think 2012 needs and update.
In case you're still running a 2008 server - upgrade it to a newer one. That one is EOL.

Google Cloud PubSub V1 using GCloud Emulator

I'm fighting with Google Docs for setting up Cloud PubSub with .NET using a PubSub emulator.
https://cloud.google.com/dotnet/docs/getting-started/using-pub-sub
https://cloud.google.com/pubsub/docs/publisher
https://cloud.google.com/pubsub/docs/emulator
Coming from a Rails background, I'm tasked to implement Cloud PubSub for a .NET product, running our google cloud on .NET Core, to enable it to publish.
Google::Cloud::Pubsub.new(project: project_id, emulator_host: emulator_host)
From the documentation using .NET, I keep coming back to the following:
PublisherServiceApiClient publisherClient = PublisherServiceApiClient.Create();
PublisherClient publisher = PublisherClient.Create(...)
However, the library used from the docs Google.Cloud.PubSub.V1 -Pre
does not contain the definition.
'PublisherClient' does not contain a definition for 'Create'.
Instead, I get CreateAsync that takes in TopicName, PublisherClient.ClientCreationSettings and PublisherClient.Settings.
https://googleapis.github.io/google-cloud-dotnet/docs/Google.Cloud.PubSub.V1/api/Google.Cloud.PubSub.V1.PublisherClient.html
I noticed that PublisherServiceApiClient can take in a Channel, but I'm confused on how to get this going.
To conclude with an actual question, how does one currently implement Cloud PubSub with .NET for in cloud and then locally with emulator? Adding to that, am I using the wrong library or the wrong docs?
Any suggestions, pointers or piece of advice would be truly appreciated.
I managed a solution that I am happy with.
Instead of using the PublisherClient, I went with using the PublisherServiceApiClient alone.
emulatorAddr = Environment.GetEnvironmentVariable("PUBSUB_EMULATOR_HOST");
if (emulatorAddr != null)
{
channel = new Channel(emulatorAddr, ChannelCredentials.Insecure);
pub = PublisherServiceApiClient.Create(channel);
}
else
{
pub = PublisherServiceApiClient.Create();
}
Which meant that publishing was slightly more involved then sending string to the PublisherClient, but overall not so bad.
PubsubMessage msg = new PubsubMessage
{
Data = ByteString.CopyFromUtf8(JsonConvert.SerializeObject(payload))
};
pub.PublishAsync(topic, new[]{ msg });
If the project is running in a Google Compute Engine, it will have default credentials. Otherwise, wether you're running an emulator locally or in docker you can define PUBSUB_EMULATOR_HOST.
What really helped was this https://googleapis.github.io/google-cloud-dotnet/docs/Google.Cloud.PubSub.V1/index.html
To make the PublisherClient connect to a local emulator, you need to pass custom ServiceEndpoint and ChannelCredentials to CreateAsync:
var serviceEndpoint = new ServiceEndpoint(theEmulatorHost, theEmulatorPort);
var publisherClient = await PublisherClient.CreateAsync(
topicName,
new PublisherClient.ClientCreationSettings(credentials: ChannelCredentials.Insecure, serviceEndpoint: serviceEndpoint));
To switch to the real PubSub, just leave away the ClientCreationSettings.
You can use the EmulatorDetection property on the ClientCreationSettings using extension method .WithEmulatorDetection(EmulatorDetection.EmulatorOrProduction). Like this:
PublisherClient publisher = await PublisherClient.CreateAsync(
topicName,
new PublisherClient.ClientCreationSettings()
.WithEmulatorDetection(EmulatorDetection.EmulatorOrProduction));
This will work if you have the following environment variable for the local emulator endpoint: PUBSUB_EMULATOR_HOST=localhost:8085
(If you use Visual Studio you might have to restart VS for the environment variable to be detected)
In windows I had problems using the set PUBSUB_EMULATOR_HOST=localhost:8085 command, so I ended up adding it manually.
Details here: https://cloud.google.com/pubsub/docs/emulator
Extra tip: you can add topics directly to API using curl: curl -X PUT http://localhost:8085/v1/projects/my-project-name/topics/my-topic

Xamarin.Forms with WCF

Usually I write a small topic with a question, but not today. I apologize in advance for "a lot of text", but this question exhausted me completely.
The main task was to create Xamarin.Forms application and organize communication with the database through WCF
Visual Studio 2015 pro, latest updates, Xamarin, latest updates.
Step 1.
This link became the foundation of my decision. I created the WCF Service as specified in this topic. At first - without Configuring Remote Access to IIS Express.
Add: WCF Service tested with Windows Forms Application. Test passed.
Step 2.
As I indicated earlier - Xamarin.Forms, not Xamarin.Android as in that topic. Here is my steps to create Xamarin.Forms project:
New Project - Cross-Platform - Cross Platform App(Xamarin.Forms or Native) - Blank App(UI Technology) - Xamarin.Forms, Code Sharing Strategy - PCL(Portable Class Library)
Step 3.
The first problems: Default template for Xamarin.Forms in VS2015 includes target platforms incompatible with WCF. It means we can't add Service Reference to PCL while we have this target platforms. This problem took a lot of time, and my solutions are:
Delete From NuGet Xamarin.Forms - restart VS - Open PCL Properties - Click Change Target Platforms - Remove Windows Phone and Silverlight - restart VS - Add Xamarin.Forms NuGet - the best one I found
Rename packages.config to packages.config.BAK - do the same operation with changing platforms
After one of this ways - "Add Service Reference" apears. The second way leads to crash VS when try to add service reference.
Step 4.
We can try to add Service Reference from VS as mentioned in guide from Xamarin site in " blue note " or generate Service client class with SLsvcUtil.exe
My client side:
public MainPage()
{
InitializeComponent();
BasicHttpBinding binding = CreateBasicHttp();
MyServiceClient client = new MyServiceClient(binding, new EndpointAddress("http://localhost:9607/MyService.svc"));
client.DoWorkCompleted += Client_DoWorkCompleted;
client.DoWorkAsync(10);
}
private void Client_DoWorkCompleted(object sender, DoWorkCompletedEventArgs e)
{
var result = e.Result;
}
private static BasicHttpBinding CreateBasicHttp()
{
BasicHttpBinding binding = new BasicHttpBinding
{
Name = "basicHttpBinding",
MaxBufferSize = 2147483647,
MaxReceivedMessageSize = 2147483647
};
TimeSpan timeout = new TimeSpan(0, 0, 30);
binding.SendTimeout = timeout;
binding.OpenTimeout = timeout;
binding.ReceiveTimeout = timeout;
return binding;
}
Step 5.
Run Service... Run Client... Wait for raise DoWorkComleted... get System.Reflection.TargetInvocationException in e.Result...
Anyone... Help me, please. This problem controls my life. I can't sleep, I can't eat... I just thinking about this ... problem...
Link to my DropBox for source code.
Fixed. The main problem: hocalhost for emulator isn't localhost for main workstation. Creating access for local network fixed my problem.

How to consume Windows Communication Foundation (WCF) by a Windows Service

When i create a Windows Service for getting information from a Web Application(ASP.NET c#) for scheduling some task in the client machine.
To consume WCF from the web application. I added WCF reference
to Window Service project as a service reference, everything seems fine. It
updated app.config file, added service reference etc.
it was not working. Any idea will be very helpful.
My Code is shown below
string result = string.Empty;
BasicHttpBinding myBinding = new BasicHttpBinding();
EndpointAddress myEndpoint = new EndpointAddress("http://test.com/Service.svc/DevicesService");
using (ChannelFactory<IDevicesService> myChannelFactory = new ChannelFactory<IDevicesService>(myBinding, myEndpoint))
{
IDevicesService wcfClient1 = myChannelFactory.CreateChannel();
result = wcfClient1.CheckNetworkConnection(IPLocalHost);
if (!string.IsNullOrEmpty(result) && result.Equals(IPLocalHost))
{
EventLog.WriteEntry("Test connection succeeded");
}
else
{
EventLog.WriteEntry("No live connection currently available");
}
((IClientChannel)wcfClient1).Close();
}
I find it easier, when building a windows service, to build a console application that performs the same work as the service will. I abstract out the actual working code (e.g. your code snippet above) into a separate assembly and then just invoke it from either my service's start method or the console's main method.
If you move your code above into a console application, does it work? If it doesn't, can you step through it and let us know where it fails. And when it fails, what exception information are you seeing?
Let us know and we'll help!

Can a WebServiceHost be changed to avoid the use of HttpListener?

I am looking for a way to use a WCF WebServiceHost without having to rely on the HttpListener class and it's associated permission problems (see this question for details).
I'm working on a application which communicates locally with another (third-party) application via their REST API.
At the moment we are using WCF as an embedded HTTP server. We create a WebServiceHost as follows:
String hostPath = "http://localhost:" + portNo;
WebServiceHost host = new WebServiceHost(typeof(IntegrationService), new Uri(hostPath));
// create a webhttpbinding for rest/pox and enable cookie support for session management
WebHttpBinding webHttpBinding = new WebHttpBinding();
webHttpBinding.AllowCookies = true;
ServiceEndpoint ep = host.AddServiceEndpoint(typeof(IIntegrationService), webHttpBinding, "");
host.Open()
ChannelFactory<IIntegrationService> cf = new ChannelFactory<IIntegrationService>(webHttpBinding, hostPath);
IIntegrationService channel = cf.CreateChannel();
Everything works nicely as long as our application is run as administrator. If we run our application on a machine without administrative privileges the host.Open() will throw an HttpListenerException with ErrorCode == 5 (ERROR_ACCESS_DENIED).
We can get around the problem by running httpcfg.exe from the command line but this is a one-click desktop application and that's not really as long term solution for us.
We could ditch WCF and write our own HTTP server but I'd like to avoid that if possible.
What's the easiest way to replace HttpListener with a standard TCP socket while still using all of the remaining HTTP scaffolding that WCF provides?
Your problem is not related to HttpListener.
Your problem is:
* You have a oneClick application with limited permissions that
* Tries to open a Server port.
This is a contradiction. An untrusted limited permission application should NOT OPEN A SERVER PORT. This is why this is not allowed per definition.
Have you tried opening a normal socket port? It should not work either.
In general, limited trust end user applications should not host a web service ;)
That said, I ahve been in a similar situation trying to use WCF in a driver communication scenario - thank heaven my application runs with full permission.
You can easily compose your own stack via CustomBinding, using the higher level protocol stuff "as is", and rolling your own version of HttpTransport that isn't backed by HttpListener or IIS. Do-able, sure, but it's a lot of work. Take the existing HttpTransport bits apart with Reflector- there are a LOT of moving parts in there. You could probably hack up a simple PoC over Socket in a day or two if you don't need anything fancy like HTTPS or chunking, but making it robust will be tricky. Here's a good wrapup of a bunch of resources (may be a bit dated now).
You could also look at ripping apart enough of Cassini to make it hostable in your app, and loading the WCF pipeline in there (via .svc files and the service activation handler)- it'd require writing very little new code that way, but still give you a fairly robust and tested webserver.

Categories