Google Cloud PubSub V1 using GCloud Emulator - c#

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

Related

Blazor App: Container.ReadItemAsync fails to connect to Azure Database when AddAuthentication used

I'm using C# in Visual Studios to create a Blazor App to connect to an Azure Database. Bit new to Blazor/Azure but I managed to get it working and retrieve the data.
I was initially using IServiceCollection.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie()
This all works fine, I'm looking to use Azure's Active Directory to verify users, which seems to work on its own, but now when the code does:
await Container.ReadItemAsync
it doesn't return the ItemResponse (or anything at all).
I've tried Googling the issue, but I haven't found anything relevant. I assume that there is an issue connecting to the azure DB relating to permissions, but I can't work out how to change it. Being new to cloud development, I'm not versed in the lingo. :)
Thanks,
Please try this:
Instead of string use JObject to return value.
instead of:
ItemResponse<string> result = await container.ReadItemAsync<string>(documentDBStorageId, PartitionKey.None, iro);
use this code:
ItemResponse<JObject> result = await container.ReadItemAsync<JObject>(documentDBStorageId, PartitionKey.None, iro);
return result.Resource.ToString();

Why would Azure Search Indexer stop working on a Live app

I have a .Net/C# app that calls the Azure Search Service. It's been working fine to find a list of PDF files I have in Azure storage based on keywords submitted. But a couple of days ago, the live app on Azure stopped working - no documents are returned from a search. However, on Local, the app works fine with the same code. I'm suspecting something may have changed with firewall rules, but I can't find where that may have occurred. Hopefully someone has had something similar happen and has a solution.
Here's the code that stopped working on Live.
var indexClient = GetIndexClient(); // sets up SearchIndexClient with uri, credentials, etc.
SearchParameters sp =
new SearchParameters()
{
Select = new[] { "metadata_storage_name" },
SearchMode = SearchMode.Any
};
var docs = indexClient.Documents.Search(searchString, sp); // this line no longer works on Live
As it turns out, it had to do with Microsoft's TLS 1.1 and 1.0 decommissioning in the last 2 weeks. I was able to add the following to my code to make it work again (added to my page_load procedure in the default template):
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
However, I'm still working on an issue where the PDF links that are listed in an editor window (using CKEditor extension), will no longer work. I'm assuming this is the same problem, as it works on my local, but not from the Azure web app.

Connect to Watson DiscoveryService through a proxy using .net/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");

Connect to offline directline routing to local echo bot based on Microsoft Bot Framework

I want to create a Line messaging bot using API wrapper provided by pierre3 hosted on local environment.
Line Messaging Service ~~POST~~> WebApi.Net ~X-> Offline-Directline ---> Echobot (Bot Framework)
I am using the node package "offline-directline" which should enable to route
messages to the local bot, created from Echobot template bundled in
Microsoft BotFramework Extension.
This is the text printed on the node terminal:
Offline-Directline: Listening for messages from client on http://127.0.0.1:3000
Routing messages to bot on http://localhost:3978/api/messages
So far, my webapi is able to receive the request from Line Messenging Service.
The problem is I don't know how to connect from webapi to the offline-directline.
DirectLineClient doesnt throw exception, but
whenever the webapi execute StartConversationAsync(), the conversation always return null.
I can confirm my Echobot is working, because I can interact with it using Bot Framework Emulator.
var uri = new Uri("http://localhost:3978/api/messages");
var cred = new DirectLineClientCredentials(null, http://localhost:3000/directline");
this.dlClient = new DirectLineClient(uri, cred);
var conversation = await dlClient.Conversations.StartConversationAsync();
//this is always return null
I expect when I send the text "hello world" via Line Messenger,
the bot will respond with the same text "hello world" on Line Messenger.
And for extra information, I am not sure this is relevant or not:
the Line Messaging Api Wrapper require to use Azure blob storage.
I don't have a online Azure Blob Storage, instead I am using Storage Emulator and set the connection string to "UseDevelopmentStorage=true".
I assume this is working because I have checked the instance of CloudBlobClient is not null and it contains the valid uri pointing to local emulator.
--
I have stuck on this for many hours yet having no clue.
Any help would be much appreciated.

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

Categories