Connecting to Neo4j Aura with .NET Core 2.2 web api - neo4j

I am trying to connect a to Neo4j Aura instance from a .NET core 2.2 web api. I understand I need the Neo4j .Net Driver v4.0.0-alpha01, but I do not seem to be able to connect. There aren't very many examples out there as this driver is new and so is Aura.
I keep getting:
Failed after retried for 6 times in 30000 ms. Make sure that your database is online and retry again.
I configure the driver as such
public void ConfigureServices(IServiceCollection services)
{
string uri = "neo4j://1234567.databases.neo4j.io:7687";//not actual subdomain
string username = "neo4j";
string password = "seeeeeeecret";//not actual password
services.AddCors();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddSingleton(GraphDatabase.Driver(uri, AuthTokens.Basic(username, password)));
}
and in my test controller i run this
private async Task<string> Neo4JTestAsync()
{
string db = "MyDb";
string message = "TESTMESSAGE";
IAsyncSession session = _driver.AsyncSession(o => o.WithDatabase(db));
try
{
var greeting = session.WriteTransactionAsync(async tx =>
{
var result = tx.RunAsync("CREATE (a:Greeting) " +
"SET a.message = $message " +
"RETURN a.message + ', from node ' + id(a)",
new { message });
var res = await result;
return "return something eventually";
});
return await greeting;
}
catch (Exception e)
{
return e.Message; // throws "Failed after retried for 6 times in 30000 ms. Make sure that your database is online and retry again"
}
finally
{
await session.CloseAsync();
}
}

I can't get the exact error message you do - but I'm pretty sure this is due to encryption - one of the big differences between the 1.x and 4.x drivers is the default position on Encryption - which is now off by default.
So you'll want to change your initialisation to:
services.AddSingleton(GraphDatabase.Driver(uri, AuthTokens.Basic(username, password), config => config.WithEncryptionLevel(EncryptionLevel.Encrypted)));
That should get you going. Also - make sure you stick with the neo4j:// protocol, as that'll route you properly.

Have you tried bolt:// in the connection string?
string uri = "bolt://1234567.databases.neo4j.io:7687";//not actual subdomain

Related

How to check elasticksearch health with different metrics in single API call?

I need to read following elasticksearch metrics
Version
Up-time
No. of Jobs
Overall Health
No. of Nodes
Disk Available in %
JVM Heap Size
No. of Indices
Primary Shards
Replica Shards
in ASP.Net MVC application. My question :-
Is it possible to read all above metrics with one API call in elasticsearch?
I have written following method
private static string CheckESHealth()
{
string esurl = "http://localhost:9200/_cluster/health";
HttpClient httpClient = new HttpClient();
string strReturnVal = string.Empty;
try
{
var response = httpClient.GetAsync(new Uri(esurl)).Result;
if (response.IsSuccessStatusCode)
{
var esdata = response.Content.ReadAsStringAsync().Result;
if (!string.IsNullOrEmpty(esdata))
{
JObject jobject = JObject.Parse(esdata);
//as a example i have taken only status.. but i need all paramters mention above
strReturnVal = jobject["status"].ToString();
}
}
else
{
strReturnVal = "Errored : Received status code : " + response.StatusCode;
}
}
catch (Exception ex)
{
strReturnVal = "Errored : " + ex.Message;
}
return strReturnVal;
}
in above example i am using :- GET _cluster/health command which give following result
enter image description here
but i am trying to read all above metrics in one API call
I didn't find a way to read above[in question] mentioned metrics in one query. so, i used following queries to get metrics.
http://localhost:9200/_cat/health?h=cluster,status,node.total,shards,pri,relo&format=json
http://localhost:9200/_cat/nodes?h=version,uptime,heap.percent&format=json
http://localhost:9200/_cat/allocation?h=disk.percent&format=json

How to handle long lasting Microsoft Cognitive Services Text-To-Speech calls in Twilio Flow

Calling a .net core based webapi from Twilio flow fails due to the fact that, because the underlying call of the webapi to Microsoft cognitive service lasts more than 5 seconds. any idea on how to make the call perform faster?
I have created a .net core based WebAPI controller that generates mp3 file that is generated by Microsoft Cognitive speech-to-text service. working great.
However, when calling it from a Twilio flow, the flow fails due to the fact that the tts service takes about more than 5 seconds to complete. The first phase - getting an access token from MS takes about 2.5 seconds, and than the tts itself takes about 3 seconds. 5 seconds is the maximum that Twilio allows for a call to return, so it fails.
any idea on how to manage the Cognitive service access token (valid for 10 minutes, by Microsoft) so it will be regenerated in parallel, so I won't have to spend 2.5 seconds every call?
I can't use Twilio's text-to-speech service since Twilio do not support Hebrew (they support Hebrew only for speech-to-text).
public class AzureSSAuthentication
{
public string subscriptionKey;
private string tokenFetchUri;
public AzureSSAuthentication(string tokenFetchUri, string subscriptionKey)
{
if (string.IsNullOrWhiteSpace(tokenFetchUri))
{
throw new ArgumentNullException(nameof(tokenFetchUri));
}
if (string.IsNullOrWhiteSpace(subscriptionKey))
{
throw new ArgumentNullException(nameof(subscriptionKey));
}
this.tokenFetchUri = tokenFetchUri;
this.subscriptionKey = subscriptionKey;
}
public async Task<string> FetchTokenAsync()
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", this.subscriptionKey);
UriBuilder uriBuilder = new UriBuilder(this.tokenFetchUri);
var result = await client.PostAsync(uriBuilder.Uri.AbsoluteUri, null).ConfigureAwait(false);
return await result.Content.ReadAsStringAsync().ConfigureAwait(false);
}
}
}
/////////////// Controller
[Route("api/[controller]")]
public class TTSController : Controller
{
// GET api/values/SomethingToSay
[HttpGet("{text}")]
[Route("Say")]
public async Task<FileContentResult> Get(string text)
{
string accessToken;
AzureSSAuthentication auth = new AzureSSAuthentication("https://westeurope.api.cognitive.microsoft.com/sts/v1.0/issuetoken", "<MyToken>");
//try
//{
accessToken = await auth.FetchTokenAsync().ConfigureAwait(false);
string host = "https://westeurope.tts.speech.microsoft.com/cognitiveservices/v1";
string body = #"<speak version='1.0' xmlns='https://www.w3.org/2001/10/synthesis' xml:lang='he-IL'>" +
"<voice name='Microsoft Server Speech Text to Speech Voice (he-IL, Asaf)'>" +
text + "</voice></speak>";
using (var client = new HttpClient())
{
using (var request = new HttpRequestMessage())
{
// Set the HTTP method
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(host);
request.Content = new StringContent(body, Encoding.UTF8, "application/ssml+xml");
request.Headers.Add("Authorization", "Bearer " + accessToken);
request.Headers.Add("Connection", "Keep-Alive");
request.Headers.Add("User-Agent", "sayWhat");
request.Headers.Add("X-Microsoft-OutputFormat", "riff-24khz-16bit-mono-pcm");
using (var response = await client.SendAsync(request).ConfigureAwait(false))
{
response.EnsureSuccessStatusCode();
// Asynchronously read the response
using (var dataStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
{
byte[] dataByteArray = new byte[dataStream.Length];
dataStream.Read(dataByteArray, 0, (int)dataStream.Length);
return File(dataByteArray, "audio/mpeg", "audio.mp3");
}
}
}
}
//}
//catch (Exception ex)
//{
// return BadRequest(ex.Message);
//}
}
}
It just takes too long.
I am looking at doing something very similar and I am concerned about the time for the MS services also. I am also dealing with text-to-speech. The flow I was considering was to call the MS Cognitive services prior to call and temporarily store the MP3. Once the call is complete, delete the MP3 file. This way you already have the MP3 file prior to the even making the call.

No errors are being raised when unsuccessfully writing to Azure service bus

When writing a message to the Azure Service Bus (using Microsoft.Azure.ServiceBus standard library, not the .Net Framework version) it works fine. However, when switching networks to a network that blocks that traffic and running it again I would expect an error being raised by SendAsync yet no error is thrown, therefor the function considers the send successful even though it is not.
Am I missing some logic to make sure that errors do get raised and trapped, it seems to be inline with all the examples I have seen.
I have tried this possible solution ..
Trouble catching exception on Azure Service Bus SendAsync method
.ContinueWith(t =>
{
Console.WriteLine(t.Status + "," + t.IsFaulted + "," + t.Exception.InnerException);
}, TaskContinuationOptions.OnlyOnFaulted);
.. and at no point does ContinueWith get hit.
[HttpPost]
[Consumes("application/json")]
[Produces("application/json")]
public ActionResult<Boolean> Post(Contract<T> contract)
{
Task.Run(() => SendMessage(contract));
// Other stuff
}
private async Task<ActionResult<Boolean>> SendMessage(Contract<T> contract)
{
JObject json = JObject.FromObject(contract);
Message message = new Message();
message.MessageId = Guid.NewGuid().ToString();
message.ContentType = ObjectType;
message.PartitionKey = ObjectType;
message.Body = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(contract));
foreach (KeyValuePair<String, String> route in DataRouting)
{
JToken jToken = json.SelectToken(route.Value);
if (jToken != null)
{
message.UserProperties[route.Key] = jToken.Value<String>();
}
else
{
String routeError = $"Could not find routing information in request for: {route.Key} in {route.Value}";
Logger.LogError(routeError);
return new UnprocessableEntityObjectResult(routeError);
}
}
// Send the message
try
{
await topicClient.SendAsync(message);
}
catch(Exception ex)
{
return new UnprocessableEntityObjectResult($"'Could not transmit message to service bus - {ex.Message}'");
}
return new OkObjectResult(true);
}
I expect that the error trap would be hit if the SendAsync fails to send the message. However it essentially fire and forgets, the message send is blocked by the firewall but is never reported to the caller by throwing an error.
Ok, found the answer, but I will leave this out there in case anyone else does this to themselves. It was down to my general muppetry when putting the MVC Controller together. Set async on the Post action and configure the await on the send. Obvious really but I missed it.
public virtual async Task<ActionResult<Boolean>> Post(Contract<T> contract){}
...
// Send the message
try
{
await topicClient.SendAsync(message).ConfigureAwait(false);
return new OkObjectResult(true); // Success if we got here
}
catch(Exception ex)
{
return new UnprocessableEntityObjectResult($"'Could not transmit message to service bus - {ex.Message}'");
}

Authentication Steps to BigQuery via Windows Service

I've created a project in Big Query and within API Access pane, I've created Service Account so that i can make Big Query API accessible through windows application on behalf of user interaction. Since i am new to using and accessing Google API, I want to know the basic steps so that i can access Big Query via Windows Service.
There are some .NET code samples here using web-based OAuth flows:
Google BigQuery with .NET documentation/ samples
For an example from another dev using service accounts in .NET, see this:
Google OAuth2 Service Account Access Token Request gives 'Invalid Request' Response
These manually implement service accounts on top of the .NET library. The .NET library has recently added native support for service accounts, though I haven't yet found an official example.
Here's an unofficial sample working with the Analytics API. It should be directly analogous to using service accounts with BigQuery:
How do I use a Service Account to Access the Google Analytics API V3 with .NET C#?
Finally here's the working code for Authentication process to Big Query API and retrieving records from Big Query table:-
I've created a class having a method of return type OAuth2Authenticator<AssertionFlowClient>.
internal class clsGetOAuth2Authentication
{
public OAuth2Authenticator<AssertionFlowClient> objGetOAuth2(string strPrivateFilePath, string strPrivateFilePassword, string strServiceAccEmailId,string strScope)
{
AuthorizationServerDescription objAuthServerDesc;
X509Certificate2 objKey;
AssertionFlowClient objClient;
OAuth2Authenticator<AssertionFlowClient> objAuth = null;
string ScopeUrl = "https://www.googleapis.com/auth/" + strScope;
string strSrvAccEmailId = strServiceAccEmailId;
string strKeyFile = strPrivateFilePath; //KeyFile: This is the physical path to the key file you downloaded when you created your Service Account.
string strKeyPassword = (strPrivateFilePassword != "") ? strPrivateFilePassword : "notasecret"; //key_pass: This is probably the password for all key files, but if you're given a different one, use that.
objAuthServerDesc = GoogleAuthenticationServer.Description; //objAuthServerDesc: Description of the server that will grant Authentiation.
objKey = new X509Certificate2(strKeyFile, strKeyPassword, X509KeyStorageFlags.Exportable); //objkey: Load up and decrypt the key.
objClient = new AssertionFlowClient(objAuthServerDesc, objKey) { ServiceAccountId = strSrvAccEmailId, Scope = ScopeUrl }; //objClient: Using the AssertionFlowClient, because we're logging in with our certificate.
objAuth = new OAuth2Authenticator<AssertionFlowClient>(objClient, AssertionFlowClient.GetState); //objAuth: Requesting Authentication.
return objAuth;
}
}
Now, another class calls the above method:-
clsGetOAuth2Authentication objOAuth2 = new clsGetOAuth2Authentication();
try
{
var objAuth = objOAuth2.objGetOAuth2(strKeyFile, strKeyPassword, strSrvAccEmailId, strScope); //Authentication data returned
objBQServ = new BigqueryService(objAuth); //Instantiate BigQueryService with credentials(objAuth) as its parameter
#region Retrieving Records:-
JobsResource j = objBQServ.Jobs;
QueryRequest qr = new QueryRequest();
qr.Query = strQuery;
DateTime dtmBegin = DateTime.UtcNow;
QueryResponse response = j.Query(qr, strProjId).Fetch();
DateTime dtmEnd = DateTime.UtcNow;
string strColHead = "";
foreach (var colHeaders in response.Schema.Fields)
{
strColHead += colHeaders.Name.ToString() + "\t";
}
Console.WriteLine(strColHead);
int intCount = 0;
foreach (TableRow row in response.Rows)
{
intCount += 1;
List<string> list = new List<string>();
foreach (var field in row.F)
{
list.Add(field.V);
}
Console.WriteLine(String.Join("\t", list));
}
TimeSpan tsElapsed = dtmEnd - dtmBegin;
Console.WriteLine("\n" + "Total no. of records:- " + intCount + ". Time taken:- " + tsElapsed);
#endregion
}
catch (Exception ex)
{
Console.WriteLine("Error Occured!" + "\n\n" + "Statement:- " + ex.Message.ToString() + "\n\n" + "Description:- " + ex.ToString() + "\n\n");
Console.WriteLine("\nPress enter to exit");
Console.ReadLine();
}

Blackberry: Make a iterative HTTP GET petition using Comms API

I want to store position coords (latitude, longitude) in a table in my MySQL DB querying a url in a way similar to this one: http://locationstore.com/postlocation.php?latitude=var1&longitude=var2 every ten seconds. PHP script works like a charm. Getting the coords in the device ain't no problem either. But making the request to the server is being a hard one. My code goes like this:
public class LocationHTTPSender extends Thread {
for (;;) {
try {
//fetch latest coordinates
coords = this.coords();
//reset url
this.url="http://locationstore.com/postlocation.php";
// create uri
uri = URI.create(this.url);
FireAndForgetDestination ffd = null;
ffd = (FireAndForgetDestination) DestinationFactory.getSenderDestination
("MyContext", uri);
if(ffd == null)
{
ffd = DestinationFactory.createFireAndForgetDestination
(new Context("MyContext"), uri);
}
ByteMessage myMsg = ffd.createByteMessage();
myMsg.setStringPayload("doesnt matter");
((HttpMessage) myMsg).setMethod(HttpMessage.POST);
((HttpMessage) myMsg).setQueryParam("latitude", coords[0]);
((HttpMessage) myMsg).setQueryParam("longitude", coords[1]);
((HttpMessage) myMsg).setQueryParam("user", "1");
int i = ffd.sendNoResponse(myMsg);
ffd.destroy();
System.out.println("Lets sleep for a while..");
Thread.sleep(10000);
System.out.println("woke up");
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("Exception message: " + e.toString());
e.printStackTrace();
}
}
I haven't run this code to test it, but I would be suspicious of this call:
ffd.destroy();
According to the API docs:
Closes the destination. This method cancels all outstanding messages,
discards all responses to those messages (if any), suspends delivery
of all incoming messages, and blocks any future receipt of messages
for this Destination. This method also destroys any persistable
outbound and inbound queues. If Destination uses the Push API, this
method will unregister associated push subscriptions. This method
should be called only during the removal of an application.
So, if you're seeing the first request succeed (at least sometimes), and subsequent requests fail, I would try removing that call to destroy().
See the BlackBerry docs example for this here
Ok so I finally got it running cheerfully. The problem was with the transport selection; even though this example delivered WAP2 (among others) as an available transport in my device, running the network diagnostics tool showed only BIS as available. It also gave me the connection parameters that I needed to append at the end of the URL (;deviceside=false;ConnectionUID=GPMDSEU01;ConnectionType=mds-public). The code ended up like this:
for (;;) {
try {
coords.refreshCoordinates();
this.defaultUrl();
this.setUrl(stringFuncs.replaceAll(this.getUrl(), "%latitude%", coords.getLatitude() + ""));
this.setUrl(stringFuncs.replaceAll(this.getUrl(), "%longitude%", coords.getLongitude() + ""));
cd = cf.getConnection(this.getUrl());
if (cd != null) {
try {
HttpConnection hc = (HttpConnection)cd.getConnection();
final int i = hc.getResponseCode();
hc.close();
} catch (Exception e) {
}
}
//dormir
Thread.sleep(15000);
} catch (Exception e) {
} finally {
//cerrar conexiones
//poner objetos a null
}
Thanks for your help #Nate, it's been very much appreciated.

Resources