Connect to Watson DiscoveryService through a proxy using .net/c# - c#

Can't connect to Watson Discovery Service while behind a corporate proxy, using C#
I read the documentation, and searched online but only a reference to a NodeJS based implementation. There was also someone looking for a solution to the same problem but using Java, and what was proposed was to extend the current api to add a method to support proxy.
IamAuthenticator authenticator = new IamAuthenticator(
apikey: "{apikey}"
);
DiscoveryService discovery = new DiscoveryService("2019-04-30", authenticator);
discovery.SetServiceUrl("{url}");
var result = discovery.CreateEnvironment(
name: "my_environment",
description: "My environment"
);
Console.WriteLine(result.Response);
The code above comes straight for the documentation and it works fine, as long as I'm not behind a proxy.
I want to know if I'm missing something or Watson .net SDK doesn't support proxies. I already asked in IBM developer forum but no answers.

Did you try to set proxies argument? This is the python version, but maybe
proxies={'proxies.https' : 'your_proxy', 'proxies.http' : 'your_proxy'}

You should be able to set the proxy via http_proxy or https_proxy environment variable. You can set this in the application environment using
set http_proxy=http://proxy.server.com:3128
from cmd.
You can also set this in the application using
Environment.SetEnvironmentVariable("http_proxy", "http://proxy.server.com:3128");

Related

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

Writing Variables via QuickOPC in C# (Visual Studio)

my project is about writing an OPC UA Client, to read and write variables on a Siemens PLC OPC UA Server. I'm using Visual Studio 2017 Enterprise and installed the Quick OPC Toolkit from OPClabs to get started and try to connect. To program the client, I'm using Windows Forms and C#.
Connecting with the server and reading variables is working just fine, but writing them gives me a headache:
1.) Before I started programming on my own, I downloaded the OPC UA Sample Client from the OPC Foundation (if someone needs the download-link just ask, the download is hard to find). I connected to the server and could browse through the variables, but the write function was greyed out/not available.
2.) I started programming a very simple client, but also failed to write variables. Reading via Live Binding (http://opclabs.doc-that.com/files/onlinedocs/QuickOpc/2018.2/User%27s%20Guide%20and%20Reference-QuickOPC/webframe.html#Making%20a%20first%20OPC%20UA%20application%20using%20Live%20Binding.html) is working, also reading them by using easyUAClient.Read() works. I tried to write a variable with this code:
namespace ErsteOPCUAVerbindung{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var easyUAClient = new EasyUAClient();
easyUAClient.WriteValue("opc.tcp://OpcUaClient:password#192.168.216.1:4840/", "nsu=SinumerikVarProvider;ns=2;s=/NC/_N_NC_TEA_ACX/$MN_PLC_CYCLIC_TIMEOUT", 1);
}
}}
but I keep getting an exception:
OpcLabs.EasyOpc.UA.OperationModel.UAException: "An OPC-UA operation failure with error code -2144010240 (0x80350000) occurred, originating from 'OpcLabs.EasyOpcUA'. The inner OPC-UA service exception with service result 'BadAttributeIdInvalid' contains details about the problem."
{"OPC-UA service result - An error specific to OPC-UA service occurred.\r\n---- SERVICE RESULT ----\r\nStatusCode: {BadAttributeIdInvalid} = 0x80350000 (2150957056)\r\n"}
I have no idea what is causing this. I suspected, that maybe some kind of access restriction is the reason, but I can't find any hints about it in the documentations and besides I'm logged in as administrator anyway.
Has anyone an Idea? Thank you.
I have had one more look at your code, and the way you pass in the user name and password (in the URL itself) is definitely not correct. The way it is given now it is essentially ignored. It may or may not be the cause for the problem with the Write, but it definitely needs to be changed. The proper way of specifying the user name and password would be:
var client = new EasyUAClient();
var endpointDescriptor = new UAEndpointDescriptor("opc.tcp://192.168.216.1:4840/");
endpointDescriptor.UserIdentity = UserIdentity.CreateUserNameIdentity("OpcUaClient", "password");
client.WriteValue(endpointDescriptor, "nsu=SinumerikVarProvider;ns=2;s=/NC/_N_NC_TEA_ACX/$MN_PLC_CYCLIC_TIMEOUT", 1);
Update: I found a documentation, which explained, that the administrator does not have write rights by default and how you can change that. You need to call the methode GiveUserAccess and pass two Arguments, the Username and "SinuWriteAll" (the second one is kind of hidden). I'll try it now with C# and post my solution if it works.

How do I connect to my Service Fabric cluster from C#?

I'm trying to connect to an on-prem Service Fabric cluster from C# code to manage some services:
using System.Fabric;
...
var fabricClient = new FabricClient();
var services = await fabricClient.QueryManager.GetServiceListAsync(new Uri("fabric:/TestConsumer"));
var service = services.FirstOrDefault(e => e.ServiceName.AbsolutePath.Contains("TestManagedConsumer"));
..
(I found the above example code here.)
The problem is that I don't actually know how to connect to the cluster. The above code throws this exception:
System.Fabric.FabricElementNotFoundException: 'Application not found'
Where/how do I specify where my cluster is running? Furthermore do I need some method authentication? If I simply navigate to http://host:19080 I'm able to connect without logging in.
I'm pretty new to Service Fabric, but I've done some digging and I am not turning up much. There seems to be little to no example code out there for this type of thing. Any suggestions?
I feel pretty dumb having found what I was looking for about 5 minutes after posting this question. Doing a search for "new FabricClient" in google turned up some examples, including this page: https://github.com/Microsoft/azure-docs/blob/master/articles/service-fabric/service-fabric-connect-to-secure-cluster.md, which shows the following example:
To connect to a remote unsecured cluster, create a FabricClient instance and provide the cluster address:
FabricClient fabricClient = new FabricClient("clustername.westus.cloudapp.azure.com:19000");
I was able to connect to my cluster with this code.
There is also some good example code here: https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-deploy-remove-applications-fabricclient

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.

Interoperate between C# and Java using web services without a Java EE application server?

I'm in a difficult position: We have a 3rd party enterprise system that exposes a Java-based API. However, we are a 100% .Net oriented development team. Essentially, I need to wrap the Java API with something that C# code can call.
Web services would be great, but the only Java application server supported on our infrastructure is WebSphere 6.1. This means the ancient (and deprecated) JAX-RPC web service framework is the only way for us to expose web services. Just getting a simple proof-of-concept working here has been a nightmare (because of Java inexperience, WebSphere being awful, JAX-RPC being clunky, and lots of JAR hell).
The new JAX-WS 2.0 web service framework in JAVA EE 5 looks great-- is there any way to run this without an entire Java application server? For example, in .Net's WCF (Windows Communication Framework), you can host services pretty much anywhere you want (in-process, Windows Service, IIS 6/7 etc).
What is the most lightweight way to wrap this library with some web services?
Yes.
If you can create a Java method which is 1) annotated with #WebMetod and 2) takes the needed parameters and call into your 3'rd party code, and wrap it up as a web application you can use the Metro stack - https://metro.dev.java.net/ - with any Servlet 2.5 web container (put it in the web containers global lib folder) to expose the above method as a web service. We are using an embedded Jetty, but I've verified this works with Tomcat.
I wrote up my findings in http://archive.midrange.com/java400-l/200904/msg00071.html
I downloaded Metro 1.4 from https://metro.dev.java.net/1.4/ (version 1.5 is very new and I haven't looked at it), which eventually unpacks to several jar files.
Copy webservices-api.jar, webservices-rt.jar, webservices-extra-api.jar and webservices-extra.jar (four files) to the folder containing "blessed" jarfiles common to all of tomcat - I believe it is ${TOMCAT}/lib for Tomcat 6.[1]
In your Eclipse project eventually ending up to be a WAR file:
If your workspace JRE is Java 5, you must add webservices-api.jar to the classpath (it should not be deployed in the end). If it is Java 6 you should be able to skip this step.
Create a class foo.Ping looking like:
package foo;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
Ping is a simple web service class providing a "yes, we have contact" class.
Currently the doPing() method provides a response with the host name and
address (if available) and the current server time.
*/
#javax.jws.WebService
public class Ping {
#javax.jws.WebMethod(action = "doPing")
public String doPing() {
System.out.println("Ping.doPing() called.");
String hostName;
try {
hostName = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
hostName = "unknown (" + e.getMessage() + ")";
}
String hostAddress;
try {
hostAddress = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
hostAddress = "unknown (" + e.getMessage() + ")";
}
return "Reached '" + hostName + "' (" + hostAddress + ") at "
+ new java.util.Date() + " java.version="
+ System.getProperty("java.version", "(not set)");
}
}
In your WEB-INF/web.xml add this snippet:
<listener>
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet>
<description>JAX-WS endpoint - this servlet must handle all endpoints</description>
<display-name>webservice</display-name>
<servlet-name>webservice</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- each endpoint must have a mapping to the JAX-WS endpoint servlet -->
<servlet-mapping>
<servlet-name>webservice</servlet-name>
<url-pattern>/ws</url-pattern>
</servlet-mapping>
Create a NEW file WEB-INF/sun-jaxws.xml:
<endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime' version='2.0'>
<endpoint name='ping' implementation='foo.Ping'url-pattern='/ws'>
</endpoint
</endpoints>
Ensure that both web.xml and sun-jaxws.xml are included in the deployment!
Done!
Now deploy your war file to the Tomcat prepared above, and open "/ws" under your deployed web application. This might be http://localhost:8080/foo/ws;. This will give you a page with information including a link to WSDL for all web services, including the Ping. This link can be used directly in any WSDL processing tool, including the web service tool in Eclipse IDE for Java EE Developers and WSDCi.
Hope this helps you :)
[1] Not making them global WILL give you classloader problems!
I don't quite understand your statement "the only Java application server supported on our infrastructure is WebSphere 6.1" with respect to the question about how to run other stuff. But no, you don't need a full App Server just to expose a web service.
I think this is a good starting point for you: http://docs.codehaus.org/display/JETTY/J2se6HttpServerSPI
I ended up finding a solution that was far easier than any of the above. We created some simple classes (like the doPing() method in #Thorbjørn Ravn Andersen's answer) with the #javax.jws.WebService and #javax.jws.WebMethod annotations, then deployed them using:
string url = "http://localhost:8282/MyService"
MyService serviceInstance = new MyService();
Endpoint svc = Endpoint.publish(url, serviceInstance);
I was then able to point Visual Studio at http://localhost:8282/MyService?wsdl and generate a client. Easy as pie.
We have run a lot of requests through this service over a large span of time and have not noticed any problems. We wrapped this with the Java Service Wrapper so that it comes back up across reboots/JVM crashes, etc. A poor man's application server.
I hope this might help any other .NET developer looking to interoperate with Java without having to remap your brain to do it.
Since you can't update your version of the JDK, as I expect you are tied to what WebSphere needs, you may want to look at trying the axis famework, from apache.
This would require you to write a webservice that would just pass calls to the java code, but it should provide you the tools to get online, and it works well with older versions of java.
I expect that Jax-WS would be a problem unless by some miracle you are on JDK5 at least, then JAX-WS would be helpful, as the annotations makes the development more like the webservice model under .NET 2.0.

Categories