FirebaseAdmin FirebaseApp Check if Firebase Instance exists - c#

I have a C# project that subscribes multiple Registrations to a Topic. Because of the nature of the project and the fact that you cant check to see how many people have already subscribed to a Topic I need to make the following Async Calls to the server:
Subscribe Registrations
TopicManagementResponse response = await FirebaseMessaging.DefaultInstance.SubscribeToTopicAsync(registrationTokens, topic);
Send message to Topic
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
Unsubscribe Registrations
TopicManagementResponse response = await FirebaseMessaging.DefaultInstance.UnsubscribeFromTopicAsync(registrationTokens, topic);
Because there are three calls I need to Create an Instance of the FirebaseApp using Credentials:
FirebaseApp.Create(new AppOptions()
{
Credential = GoogleCredential.FromFile(path),
});
BUT because the async posts return a "WaitingForActivation" response (yet it does correctly do what it is supposed to do) I cant Delete the Instance to move on to the next function as it throws an error as it cant re-create another FirebaseApp Instance - It fails if I give it a name so I cant use GetInstance(string name).
Am I missing something or is there another way to do this.
Here is an example of a subscribe function:
internal static async Task SubscribeToTopic(string path, string topic, string regID5, string regID)
{
FirebaseApp app = FirebaseApp.Create(new AppOptions()
{
Credential = GoogleCredential.FromFile(path),
});
var registrationTokens = new List<string>()
{
regID5, regID
};
// Subscribe the devices corresponding to the registration tokens to the
// topic
try
{
TopicManagementResponse response = await FirebaseMessaging.DefaultInstance.SubscribeToTopicAsync(registrationTokens, topic);
using (StreamWriter sw = System.IO.File.AppendText(HttpContext.Current.Server.MapPath("/tokens.txt")))
{
sw.WriteLine($"{response.SuccessCount} tokens were subscribed successfully");
}
}
catch (Exception ex)
{
string myerror = ex.Message;
}
}
Any ideas?

you are creating firebase instance every time. so you need to create firebase instance in application start in global.asax file.

Related

How to validate Azure Blob Storage Shared Access Signature (SAS) URL?

My application allows users to enter an Azure Blob Storage SAS URL. How would I go about validating it? I'm using the Azure Storage Blobs client library, and there doesn't seem to be any way of validating SAS URLs without actually performing a blob operation (which I don't want to do).
The validation operation can be asynchronous and involve an API call if necessary (ie it can be triggered with a button).
public class SASURLValidator
{
public async Task<bool> ValidateSASURL(string sasURL)
{
// What goes here?
}
public async Task Test()
{
var result = await ValidateSASURL("https://blobstorageaccountname.blob.core.windows.net/containerName?sp=w&st=2022-02-15T02:07:49Z&se=2022-03-15T10:07:49Z&spr=https&sv=2020-08-04&sr=c&sig=JDFJEF342JDSFJIERJsdjfkajiwSKDFJIQWJIFJSKDFJWE%3D")
// result should be true if the above is a valid SAS
}
}
You man test the list or write and delete access. Depending on your scenario you can use on of both. It would be also possible to modify the sample for testing. read access to a singe file.
private async Task TestSasAsync(String uri, bool testWriteAndDelete, bool testList)
{
try
{
var cloudBlobContainer = new CloudBlobContainer(new Uri(uri));
if (testList)
{
foreach (var blob in cloudBlobContainer.ListBlobs())
{
Console.WriteLine(blob.Uri);
}
}
if (testWriteAndDelete)
{
var blockBlob = cloudBlobContainer.GetBlockBlobReference("testBlob.txt");
await blockBlob.UploadTextAsync("Hello world");
await blockBlob.DeleteAsync();
}
}
catch (Exception ex)
{
throw new Exception("Failed to validate SAS Uri: " + ex.Message, ex);
}
}

Why I am getting AADSTS50011 error when using Microsoft OneDrive sample with UWP app

On VS2019, when using this OneDrive sample with UWP from Microsoft, I am getting the following error. An online search shows some relevant links (such as this or this or this) but their context are different (as they are using web apps or Python etc.):
AADSTS50011: The reply URL specified in the request does not match the reply URLs configured for the application: '55dbdbc9-xxxxxxxxxxxxx-a24'
I have followed the sample's instructions for Registering and Configuring the app where Redirect URI I have selected is Public client (mobile & desktop), and have set it's value to https://login.microsoftonline.com/common/oauth2/nativeclient
Question: What I may be doing wrong, and how can we resolve the issue?
UPDATE:
Error occurs at line FolderLoaded?.Invoke(this, EventArgs.Empty); of the method shown below. This is line 180 of file OneDriveList.xaml.cs in the sample. And it is not the error OperationCanceledException since error goes to the second catch statement.
private async Task LoadFolderAsync(string id = null)
{
// Cancel any previous operation
_cancellationTokenSource?.Cancel();
_cancellationTokenSource = new CancellationTokenSource();
// Check if session is set
if (AuthenticationService == null) throw new InvalidOperationException($"No {nameof(AuthenticationService)} has been specified");
// Keep a local copy of the token because the source can change while executing this function
var token = _cancellationTokenSource.Token;
// Add an option to the REST API in order to get thumbnails for each file
// https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_list_thumbnails
var options = new[]
{
new QueryOption("$expand", "thumbnails"),
};
// Create the graph request builder for the drive
IDriveRequestBuilder driveRequest = AuthenticationService.GraphClient.Me.Drive;
// If folder id is null, the request refers to the root folder
IDriveItemRequestBuilder driveItemsRequest;
if (id == null)
{
driveItemsRequest = driveRequest.Root;
}
else
{
driveItemsRequest = driveRequest.Items[id];
}
// Raise the loading event
FolderLoading?.Invoke(this, EventArgs.Empty);
try
{
try
{
// Make a API request loading 50 items per time
var page = await driveItemsRequest.Children.Request(options).Top(50).GetAsync(token);
token.ThrowIfCancellationRequested();
// Load each page
await LoadGridItemsAsync(page, token);
token.ThrowIfCancellationRequested();
}
finally
{
// Raise the loaded event
FolderLoaded?.Invoke(this, EventArgs.Empty);
}
}
catch (OperationCanceledException)
{ }
catch (Exception ex)
{
// Raise the error event
LoadingError?.Invoke(this, ex);
}
}

Best way to check if ubuntu service has stopped in c#

I want to get an alert when a service (grafana or influxdb) in an Azure virtual machine (Ubuntu 16.04) has stopped. I'd like to use c# to connect to the VM and check the status of grafana and influxdb services. Can anyone share a code sample that implements this?
Both services provide health endpoints that can be used to check their status from a remote server. There's no need to open a remote shell connection. In fact, it would be impossible to monitor large server farms if one had to SSH to each one.
In the simplest case, and ignoring networking issues, one can simply hit the health endpoints to check the status of both services. A rough implementation could look like this :
public async Task<bool> CheckBoth()
{
var client = new HttpClient
{
Timeout = TimeSpan.FromSeconds(30)
};
const string grafanaHealthUrl = "https://myGrafanaURL/api/health";
const string influxPingUrl = "https://myInfluxURL/ping";
var (grafanaOK, grafanaError) = await CheckAsync(client, grafanaHealthUrl,
HttpStatusCode.OK, "Grafana error");
var (influxOK, influxError) = await CheckAsync(client, influxPingUrl,
HttpStatusCode.NoContent,"InfluxDB error");
if (!influxOK || !grafanaOK)
{
//Do something with the errors
return false;
}
return true;
}
public async Task<(bool ok, string result)> CheckAsync(HttpClient client,
string healthUrl,
HttpStatusCode expected,
string errorMessage)
{
try
{
var status = await client.GetAsync(healthUrl);
if (status.StatusCode != expected)
{
//Failure message, get it and log it
var statusBody = await status.Content.ReadAsStringAsync();
//Possibly log it ....
return (ok: false, result: $"{errorMessage}: {statusBody}");
}
}
catch (TaskCanceledException)
{
return (ok: false, result: $"{errorMessage}: Timeout");
}
return (ok: true, "");
}
Perhaps a better solution would be to use Azure Monitor to ping the health URLs periodically and send an alert if they are down.
Here is something you can use to connect to Azure linux using SSH in c#
using (var client = new SshClient("my-vm.cloudapp.net", 22, "username", "password​"))
{
client.Connect();
Console.WriteLine("it worked!");
client.Disconnect();
Console.ReadLine();
}
Usually SSH server only allow public key auth or other two factor auth.
Change your /etc/ssh/sshd_configuncomment #PasswordAuthentication yes
# Change to no to disable tunnelled clear text passwords
#PasswordAuthentication yes
Later you can poll for installed services.
Also for an alternative solution, you can deploy a rest api in your linux VM to check the status of your service and the call it from C# httpclient for the status.
Hope it helps

Firestore real-time-updates in c#

I'm trying to subscribe to real-time updates with Cloud Firestore in c# using Google.Cloud.Firestore.V1Beta1. I'm using the following code, which receives updates for a short time, until the stream is closed. Has anyone got FirestoreClient.Listen to work?
// Create client
FirestoreClient firestoreClient = FirestoreClient.Create();
// Initialize streaming call, retrieving the stream object
FirestoreClient.ListenStream duplexStream = firestoreClient.Listen();
// Create task to do something with responses from server
Task responseHandlerTask = Task.Run(async () =>
{
IAsyncEnumerator<ListenResponse> responseStream = duplexStream.ResponseStream;
while (await responseStream.MoveNext())
{
ListenResponse response = responseStream.Current;
Console.WriteLine(response);
}
});
// Send requests to the server
var citiesPath = string.Format("projects/{0}/databases/{1}/documents/cities/CJThcwCipOtIEAm2tEMY", projectId, databaseId);
// Initialize a request
var dt = new DocumentsTarget { };
dt.Documents.Add(citiesPath);
ListenRequest request = new ListenRequest
{
Database = new DatabaseRootName(projectId, databaseId).ToString(),
AddTarget = new Target
{
Documents = dt
}
};
// Stream a request to the server
await duplexStream.WriteAsync(request);
// Await the response handler.
// This will complete once all server responses have been processed.
Console.WriteLine("Awaiting responseHandlerTask");
await responseHandlerTask;
Edit 1:
I've tried setting the expiration explicitly to never expire, but still no luck, I get 5 minutes in then receive a RST_STREAM.
//Setup no expiration for the listen
CallSettings listenSettings = CallSettings.FromCallTiming(CallTiming.FromExpiration(Expiration.None));
// Initialize streaming call, retrieving the stream object
FirestoreClient.ListenStream duplexStream = firestoreClient.Listen(listenSettings);
Edit 2:
It seems like a bit of a kludge, but I found it works to keep track of the last resetToken, catch the exception, then restart the request with the request token. I've updated the code that makes the original request to take an optional resumeToken.
ListenRequest request = new ListenRequest
{
Database = new DatabaseRootName(projectId, databaseId).ToString(),
AddTarget = new Target
{
Documents = dt
}
};
if (resumeToken != null)
{
Console.WriteLine(string.Format("Resuming a listen with token {0}", resumeToken.ToBase64()));
request.AddTarget.ResumeToken = resumeToken;
}
// Stream a request to the server
await duplexStream.WriteAsync(request);
It's not perfect, but I think it's the way Google implemented it in Node.js. It does result in an API call every 5 minutes, so there is some expense to it. Maybe that's the why it works this way?
Thanks
Until Jon finishes the official support, you can use something I put together if you need it right away. https://github.com/cleversolutions/FirebaseDotNetRamblings/blob/master/FirebaseDocumentListener.cs Its an extension method you can drop into your project and use like this:
//Create our database connection
FirestoreDb db = FirestoreDb.Create(projectId);
//Create a query
CollectionReference collection = db.Collection("cities");
Query qref = collection.Where("Capital", QueryOperator.Equal, true);
//Listen to realtime updates
FirebaseDocumentListener listener = qref.AddSnapshotListener();
//Listen to document changes
listener.DocumentChanged += (obj, e) =>
{
var city = e.DocumentSnapshot.Deserialize<City>();
Console.WriteLine(string.Format("City {0} Changed/Added with pop {1}", city.Name, city.Population));
};

C# HttpClient Uri value

I'm working on creating a WindowsPhone 8.1 app, and I'm having trouble getting the client to access the database. I created a server-side project that works fine using web api. I'm able to run debugger and add "/api/entityName" to return a list of all the rows in that table or just a single row if I specify an id value. After doing a lot of testing on the client side, I think I've pinpointed my error: the uri value. Can someone tell me what value I should be passing into the uri constructor? Here's the method that I'm using in the client:
public async void GetBars()
{
var uri = new Uri("http://localhost:20672/tables/bars"); //seems like this value is the problem
var httpClient = new HttpClient();
barsListBox.Items.Add("right before try starts");
// Always catch network exceptions for async methods
try
{
barsListBox.Items.Add("try started");
var result = await httpClient.GetStringAsync(uri); //never gets past this line. goes straight to finally
barsListBox.Items.Add("right before linq");
var queryAllBars =
from bar in result
select bar;
barsListBox.Items.Add("linq finished");
foreach (var bar in queryAllBars)
{
barsListBox.Items.Add(bar);
}
}
catch
{
// Details in ex.Message and ex.HResult.
}
finally
{
barsListBox.Items.Add("finally executed");
httpClient.Dispose();
}
}
The database is a SQL Server database being hosted on Azure. I've tried using the URL listed for the database in Azure, my current IP address, just about every combination of using/excluding the port number, etc but nothing seems to work. I don't get any errors, but I also don't get anything displayed in the UI (except for the testing statements I've entered). Try started gets printed, but right before linq doesn't, which is why I believe my problem is coming from the uri value being passed int GetStringAsync. Thanks for the help.
You can Try like this
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://Ipaddress/mammo/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync("api/controllername");
if (response.IsSuccessStatusCode)
{
IList<something> data = await response.Content.ReadAsAsync<IList<something>>();
}
}
Thanks to #Midhun's answer and other answers I received, I was able to get the bars to print correctly. I used Midhun's code above with the uri of my hosted database (the azurewebsites.net url) instead of my localhost database. I also changed the IList to a String and wrote a method that picks out the values using IndexOf and Substring as follows:
start = bar.IndexOf("BarID", start) + 7;
int end = bar.IndexOf(",", start);
int id = Convert.ToInt32(bar.Substring(start, (end - start)));
Bars newBar = new Bars(id, name, street, city, state, phone, zip);
Bars.barsList.Add(newBar);
I then created a static list in my Bars model to add the newly created Bars items to.

Categories