I am trying to access my Firestore database from a MAUI application targeting iOS (using Microsoft tools in an Apple product for Google access; a...peculiar selection of inventory, I know). I am using the NuGet package Google.Cloud.Firestore and trying to initialize an instance of FirebaseDb to access the database but nothing happens. How can I fetch data from a MAUI app targeting iOS? I tried the Xamarin library Plugin.CloudFirestore by f-miyu but cannot make it work in MAUI.
You can see the code below, and more explanations at the end of this question:
public async Task ReadCredentials()
{
System.Diagnostics.Debug.WriteLine("Start reading credentials");
using var stream = await FileSystem.OpenAppPackageFileAsync("FirestoreKey.json");
using StreamReader reader = new(stream);
var contents = reader.ReadToEnd();
System.Diagnostics.Debug.WriteLine("Credentials acquired.");
jsonCredentials = contents;
}
public void InitDb()
{
System.Diagnostics.Debug.WriteLine("Initializing database builder with credentials");
System.Diagnostics.Debug.WriteLine(jsonCredentials);
var dbBuilder = new FirestoreDbBuilder
{
JsonCredentials = jsonCredentials,
WarningLogger = (string message) => System.Diagnostics.Debug.WriteLine(message)
};
System.Diagnostics.Debug.WriteLine("Database builder initialized");
System.Diagnostics.Debug.WriteLine("Building database");
var db = dbBuilder.Build();
System.Diagnostics.Debug.WriteLine("Done");
if (db != null)
System.Diagnostics.Debug.WriteLine("Database built");
else
System.Diagnostics.Debug.WriteLine("FAILED");
}
My plist.info file contains the following lines:
<key>NSAppTransportSecurity</key>
<dict>
<key> NSAllowsArbitraryLoads</key>
<true/>
</dict>
When I run the above methods in order, the application stops at the line building the database and stops without giving me any warning or error info. The remaining lines are not even called. What I get in the console is:
Start reading credentials
Credentials acquired.
Initializing database builder with credentials
{
"type": "service_account",
"project_id": "<removed>",
"private_key_id": "<removed>",
"private_key": "-----BEGIN PRIVATE KEY-----\n<removed>\n",
"client_email": "<removed>",
"client_id": "<removed>",
"auth_uri": "<removed>",
"token_uri": "<removed>",
"auth_provider_x509_cert_url": "<removed>",
"client_x509_cert_url": "<removed>"
}
Database builder initialized
Building database
2022-05-10 12:38:17.827901+0300 istanbul-bridge-conference-maui[2999:97800] SecTaskLoadEntitlements failed error=22 cs_flags=200, pid=2999
2022-05-10 12:38:17.828092+0300 istanbul-bridge-conference-maui[2999:97800] SecTaskCopyDebugDescription: istanbul-bridge-[2999]/0#-1 LF=0
2022-05-10 12:38:17.828353+0300 istanbul-bridge-conference-maui[2999:97800] SecTaskLoadEntitlements failed error=22 cs_flags=200, pid=2999
2022-05-10 12:38:17.828536+0300 istanbul-bridge-conference-maui[2999:97800] SecTaskCopyDebugDescription: istanbul-bridge-[2999]/0#-1 LF=0
Thread started: #14
Thread started: #15
Thread finished: <Thread Pool> #6
Thread finished: <Thread Pool> #13
Thread finished: <Thread Pool> #8
Thread finished: <Thread Pool> #10
Thread finished: <Thread Pool> #12
I am partially following the steps in https://firebase.google.com/docs/firestore/quickstart#c . Since I cannot use the environmental variables in iOS as in the link, I am trying to create FirestoreDb using the json key string. If I do not add NSAllowsArbitraryLoads to the plist file, I get the following console output:
Building database
2022-05-10 11:51:03.397142+0300 istanbul-bridge-conference-maui[2603:74019] SecTaskLoadEntitlements failed error=22 cs_flags=200, pid=2603
2022-05-10 11:51:03.397375+0300 istanbul-bridge-conference-maui[2603:74019] SecTaskCopyDebugDescription: istanbul-bridge-[2603]/0#-1 LF=0
2022-05-10 11:51:03.397657+0300 istanbul-bridge-conference-maui[2603:74019] SecTaskLoadEntitlements failed error=22 cs_flags=200, pid=2603
2022-05-10 11:51:03.397820+0300 istanbul-bridge-conference-maui[2603:74019] SecTaskCopyDebugDescription: istanbul-bridge-[2603]/0#-1 LF=0
2022-05-10 11:51:03.398957+0300 istanbul-bridge-conference-maui[2603:74019] [connection] nw_socket_connect [C1:2] connect failed (fd 13) [65: No route to host]
2022-05-10 11:51:03.399110+0300 istanbul-bridge-conference-maui[2603:74019] [] nw_socket_connect connect failed [65: No route to host]
2022-05-10 11:51:03.399570+0300 istanbul-bridge-conference-maui[2603:74019] Connection 1: received failure notification
2022-05-10 11:51:03.399678+0300 istanbul-bridge-conference-maui[2603:74019] Connection 1: failed to connect 1:65, reason -1
2022-05-10 11:51:03.399767+0300 istanbul-bridge-conference-maui[2603:74019] Connection 1: encountered error(1:65)
2022-05-10 11:51:03.400501+0300 istanbul-bridge-conference-maui[2603:74019] Task <A19F42B0-05EA-46A5-A038-6F385942DB68>.<1> HTTP load failed, 0/0 bytes (error code: -1004 [1:65])
2022-05-10 11:51:03.403258+0300 istanbul-bridge-conference-maui[2603:73954] Task <A19F42B0-05EA-46A5-A038-6F385942DB68>.<1> finished with error [-1004] Error Domain=NSURLErrorDomain Code=-1004 "Could not connect to the server." UserInfo={_kCFStreamErrorCodeKey=65, NSUnderlyingError=0x6000001628b0 {Error Domain=kCFErrorDomainCFNetwork Code=-1004 "(null)" UserInfo={_NSURLErrorNWPathKey=satisfied (Path is satisfied), interface: en0, _kCFStreamErrorCodeKey=65, _kCFStreamErrorDomainKey=1}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <A19F42B0-05EA-46A5-A038-6F385942DB68>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <A19F42B0-05EA-46A5-A038-6F385942DB68>.<1>"
), NSLocalizedDescription=Could not connect to the server., NSErrorFailingURLStringKey=http://169.254.169.254/computeMetadata/v1/?recursive=true, NSErrorFailingURLKey=http://169.254.169.254/computeMetadata/v1/?recursive=true, _kCFStreamErrorDomainKey=1}
Related
2021-01-19 18:34:32.877465+0530 REPORT[7165:380896] [connection] nw_socket_handle_socket_event [C2.1:2] Socket SO_ERROR [60: Operation timed out]
2021-01-19 18:34:32.886744+0530 REPORT[7165:380896] Connection 2: received failure notification
2021-01-19 18:34:32.889254+0530 REPORT[7165:380896] Connection 2: failed to connect 1:60, reason -1
2021-01-19 18:34:32.890389+0530 REPORT[7165:380896] Connection 2: encountered error(1:60)
2021-01-19 18:34:32.892589+0530 REPORT[7165:381682] Task .<1> HTTP load failed, 0/0 bytes (error code: -1001 [1:60])
2021-01-19 18:34:32.895246+0530 REPORT[7165:380952] Task .<1> finished with error [-1001] Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={_kCFStreamErrorCodeKey=60, NSUnderlyingError=0x600002b5eca0 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo={_kCFStreamErrorCodeKey=60, _kCFStreamErrorDomainKey=1}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask .<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask .<1>"
), NSLocalizedDescription=The request timed out., NSErrorFailingURLStringKey
Have you tried something similar?
try {
//code
}
catch (TimeoutException) {
//exception handler
}
I am new to Azure. I am using the following part of the code to upload a file to Azure Blob.
public async Task<byte[]> UploadResultFile(string fileName, byte[] data)
{
if (StringUtilities.isBlankOrNull(fileName))
{
throw new EmptyStringException("File name cannot be empty or null");
}
// Creates a BlobServiceClient object which will be used to create a container client
BlobServiceClient blobServiceClient = new BlobServiceClient(config.StorageConnectionString);
// Create the container and return a container client object
BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(config.ResultContainer);
// Create a local file in the ./data/ directory for uploading and downloading
string localFilePath = Path.Combine(Experiment.DataFolder, fileName);
// Write text to the file
// Adding a check to write a data in a file only if data is not equal to null
// This is important as we need to re-use this method to upload a file in which data has already been written
if (data != null)
{
File.WriteAllBytes(localFilePath, data);
}
// Get a reference to a blob
BlobClient blobClient = containerClient.GetBlobClient(fileName);
// Open the file and upload its data
// FileStream uploadFileStream = File.OpenRead(localFilePath);
using FileStream uploadFileStream = File.OpenRead(localFilePath);
await blobClient.UploadAsync(uploadFileStream, true);
uploadFileStream.Close();
return Encoding.ASCII.GetBytes(blobClient.Uri.ToString());
}
}
But it is throwing an issue on uploadFileStream as following :
uploadFilestream.ReadOut threw an exception of type 'System.InvalidOAperationException'
uploadFilestream.WriteOut threw an exception of type 'System.InvalidOAperationException'
Subsequently, the console is throwing the following exception :
The I/O operation has been aborted because of either a thread exit or an application request
Caught an exception: Retry failed after 6 tries. (The operation was canceled.) (The operation was canceled.) (The operation was canceled.) (The operation was canceled.) (The operation was canceled.) (The operation was canceled.)
System.AggregateException: Retry failed after 6 tries. (The operation was canceled.) (The operation was canceled.) (The operation was canceled.) (The operation was canceled.) (The operation was canceled.) (The operation was canceled.)
---> System.Threading.Tasks.TaskCanceledException: The operation was canceled.
---> System.Net.Http.HttpRequestException: Error while copying content to a stream.
---> System.IO.IOException: Unable to read data from the transport connection: The I/O operation has been aborted because of either a thread exit or an application request..
---> System.Net.Sockets.SocketException (995): The I/O operation has been aborted because of either a thread exit or an application request.
Any help in identifying and solving the issue will be highly appreciated.
This is how I am uploading and it works for me. Not saying your method won't work... can't confirm or deny unless I copy your code and create an app on my machine.
using System;
using System.IO;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.WindowsAzure.Storage.RetryPolicies;
namespace My.Repositories
{
public class BlobStorageRepository
{
private readonly CloudBlobContainer _cloudContainer;
public BlobStorageRepository(string containerName, string connectionStringForStorageAccount)
{
CloudStorageAccount storageAccount;
storageAccount = CloudStorageAccount.Parse(connectionStringForStorageAccount);
var blobClient = storageAccount.CreateCloudBlobClient();
blobClient.DefaultRequestOptions = new BlobRequestOptions
{
// below timeout you can change to your needs
MaximumExecutionTime = TimeSpan.FromSeconds(30),
LocationMode = LocationMode.PrimaryThenSecondary
};
_cloudContainer = blobClient.GetContainerReference(containerName);
}
public int Save<T>(string blobName, byte[] contentBytes) where T : class
{
var bytes = contentBytes;
var blockBlob = _cloudContainer.GetBlockBlobReference($"{blobName}.json");
blockBlob.Properties.ContentType = "application/json";
using (var memoryStream = new MemoryStream(bytes))
{
blockBlob.UploadFromStream(memoryStream);
}
return bytes.Length; // returning the number of bytes uploaded.
}
}
}
Just starting to work with Azure.
Have a simple C# .NET Core app, which connects to Azure ServiceBus, reads messages, and writes them to Azure SQL database.
Works locally just fine - connects to remote Azure Service Bus Queue, reads messages, connect to remote Azure SQL db, writes records.
Same exact app, when deployed to Azure as a WebApp, appears to "run", but no longer reads messages from Services Bus, and no longer writes anything to Azure SQL.
Here is the entire app (i.e. Program.cs):
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.ServiceBus;
using System.Data.SqlClient;
namespace ServiceBusReader
{
class Program
{
const string ServiceBusConnectionString = "SB_CONNECTION_STRING";
const string QueueName = "BasicQueue";
static IQueueClient queueClient;
static SqlConnection connection = null;
public static async Task Main(string[] args)
{
System.Diagnostics.Trace.TraceError("Inside Main function...");
queueClient = new QueueClient(ServiceBusConnectionString, QueueName);
Console.WriteLine("======================================================");
System.Diagnostics.Trace.TraceError("======================================================");
Console.WriteLine("Press ENTER key to exit after receiving all the messages.");
Console.WriteLine("======================================================");
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = "XXXX.database.windows.net";
builder.UserID = "USERID";
builder.Password = "PASSWORD";
builder.InitialCatalog = "mySampleDatabase";
connection = new SqlConnection(builder.ConnectionString);
connection.Open();
// Register the queue message handler and receive messages in a loop
RegisterOnMessageHandlerAndReceiveMessages();
Console.ReadKey();
await queueClient.CloseAsync();
}
static void RegisterOnMessageHandlerAndReceiveMessages()
{
// Configure the message handler options in terms of exception handling, number of concurrent messages to deliver, etc.
var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
{
// Maximum number of concurrent calls to the callback ProcessMessagesAsync(), set to 1 for simplicity.
// Set it according to how many messages the application wants to process in parallel.
MaxConcurrentCalls = 1,
// Indicates whether the message pump should automatically complete the messages after returning from user callback.
// False below indicates the complete operation is handled by the user callback as in ProcessMessagesAsync().
AutoComplete = false
};
// Register the function that processes messages.
queueClient.RegisterMessageHandler(ProcessMessagesAsync, messageHandlerOptions);
}
static async Task ProcessMessagesAsync(Message message, CancellationToken token)
{
// Process the message.
Console.WriteLine($"Received message: SequenceNumber:{message.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(message.Body)}");
string query = "INSERT INTO [SalesLT].[messages] (message) VALUES(#Message)";
SqlCommand cmd = new SqlCommand(query, connection);
System.Diagnostics.Trace.TraceError(Encoding.UTF8.GetString(message.Body));
cmd.Parameters.AddWithValue("#Message", Encoding.UTF8.GetString(message.Body));
cmd.ExecuteNonQuery();
Console.WriteLine("Records Inserted Successfully...");
System.Diagnostics.Trace.TraceError("Records Inserted Successfully...");
// Complete the message so that it is not received again.
// This can be done only if the queue Client is created in ReceiveMode.PeekLock mode (which is the default).
await queueClient.CompleteAsync(message.SystemProperties.LockToken);
// Note: Use the cancellationToken passed as necessary to determine if the queueClient has already been closed.
// If queueClient has already been closed, you can choose to not call CompleteAsync() or AbandonAsync() etc.
// to avoid unnecessary exceptions.
}
// Use this handler to examine the exceptions received on the message pump.
static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
{
Console.WriteLine($"Message handler encountered an exception {exceptionReceivedEventArgs.Exception}.");
var context = exceptionReceivedEventArgs.ExceptionReceivedContext;
Console.WriteLine("Exception context for troubleshooting:");
Console.WriteLine($"- Endpoint: {context.Endpoint}");
Console.WriteLine($"- Entity Path: {context.EntityPath}");
Console.WriteLine($"- Executing Action: {context.Action}");
return Task.CompletedTask;
}
}
}
Should I do anything differently in this app in order to make it work in Azure?
It seems that you are trying to deploy a webjob to web app. May I know if you have set it to Continuous type? If you have set it to Continuous, the webjob will automatically run after deployment.
By default, the type is Triggered and you need to manually start the webjob from portal.
I am using Akka.Net in a very simple client server configuration. Nothing very advanced at this time. After about 3 or 4 days of sending messages back and forth it seems that the entire system gets in a disconnection state. With a restart of the services everything reconnects and there are no issues. Prior to this things will disconnect however it seems to reconnect right away.
During this time both machines are accessible on the network and don't seem to have any actual connection problems.
I am not sure where to go from here.
Client config (Server very similar)
return ConfigurationFactory
.ParseString(string.Format(#"
akka {{
loggers = [""XYZ.AkkaLogger, XYZ""]
actor {{
provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
serializers {{
json = ""XYZ.AkkaSerializer, XYZ""
}}
}}
remote {{
helios.tcp {{
transport-class = ""Akka.Remote.Transport.Helios.HeliosTcpTransport, Akka.Remote""
applied-adapters = []
transport-protocol = tcp
port = 0
hostname = {0}
send-buffer-size = 512000b
receive-buffer-size = 512000b
maximum-frame-size = 1024000b
tcp-keepalive = on
}}
transport-failure-detector {{
heartbeat-interval = 60 s # default 4s
acceptable-heartbeat-pause = 20 s # default 10s
}}
}}
stdout-loglevel = DEBUG
loglevel = DEBUG
debug {{
receive = on
autoreceive = on
lifecycle = on
event-stream = on
unhandled = on
}}
}}
", Environment.MachineName));
This cycle is pretty sporadic at first however after a while it repeats and nothing connects anymore until a reset of the service.
WARN 2015-07-31 07:22:12,994 [1584] - Association with remote system akka.tcp://SystemName#Server:8081 has failed; address is now gated for 5000 ms. Reason is: [Disassociated]
ERROR 2015-07-31 07:22:12,994 [1584] - Disassociated
Akka.Remote.EndpointDisassociatedException: Disassociated
at Akka.Remote.EndpointWriter.PublishAndThrow(Exception reason, LogLevel level)
at Akka.Remote.EndpointWriter.Unhandled(Object message)
at Akka.Remote.EndpointWriter.Writing(Object message)
at Akka.Actor.ActorCell.<>c__DisplayClass3e.<Akka.Actor.IUntypedActorContext.Become>b__3d(Object m)
at Akka.Actor.ActorBase.AroundReceive(Receive receive, Object message)
at Akka.Actor.ActorCell.ReceiveMessage(Object message)
at Akka.Actor.ActorCell.AutoReceiveMessage(Envelope envelope)
at Akka.Actor.ActorCell.Invoke(Envelope envelope)
DEBUG 2015-07-31 07:22:12,996 [1494] - Disassociated [akka.tcp://SystemName#Client:57284] -> akka.tcp://SystemName#Server:8081
DEBUG 2015-07-31 07:23:13,033 [1469] - Drained buffer with maxWriteCount: 50, fullBackoffCount: 1,smallBackoffCount: 0, noBackoffCount: 0,adaptiveBackoff: 10000
ERROR 2015-07-31 07:24:13,019 [1601] - No response from remote. Handshake timed out or transport failure detector triggered.
DEBUG 2015-07-31 07:24:13,020 [1569] - Disassociated [akka.tcp://SystemName#Client:57284] -> akka.tcp://SystemName#Server:8081
WARN 2015-07-31 07:24:13,020 [1601] - Association with remote system akka.tcp://SystemName#Server:8081 has failed; address is now gated for 5000 ms. Reason is: [Disassociated]
ERROR 2015-07-31 07:24:13,021 [1601] - Disassociated
I have written the code for Server/Client program in C#. Without using the Thread, it is working fine. If I use Thread, I am getting following error message.
The thread '' (0x9a8) has exited with code 0 (0x0).
Sample code
public class MyServer{
public MyServer (){
...
...
System.Threading.Thread socThread = new System.Threading.Thread(new System.Threading.ThreadStart(receiveSockets));
socThread.Start();
}
private void receiveSockets()
{
try
{
while(true){
IPAddress ipadd = IPAddress.Parse(systemIPAddress);
TcpListener tcp = new TcpListener(ipadd, 8001);
tcp.Start();
Console.WriteLine("Waiting for client in 8001 port no");
Socket socket = tcp.AcceptSocket();
Console.WriteLine("Client address : " + socket.RemoteEndPoint);
System.Threading.Thread socThread = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(receiveData));
socThread.Start(socket);
}
}
catch (Exception e)
{
Console.WriteLine("Error in receive Sockets : " + e.Message);
}
}
private void receiveData(object obj)
{
try
{
while(true){
Socket socket = (Socket)obj;
byte[] data = new byte[1000];
int status = socket.Receive(data);
Console.WriteLine("Received 1.");
string content = Encoding.UTF8.GetString(data, 0, 1000);
Console.WriteLine("Received data 1 : " + content);
}
}
catch (Exception e)
{
Console.WriteLine("Error in receive Data : " + e.Message);
}
}
static void Main(string[] args){
MyServer server = new MyServer();
}
Client Program
static void Main(string[] args)
{
TcpClient tcp = new TcpClient();
tcp.Connect("192.168.1.11", 8001);
Stream stream = tcp.GetStream();
String msg = "Testing...";
byte[] content = new byte[msg.Length * sizeof(char)];
System.Buffer.BlockCopy(msg.ToCharArray(), 0, content, 0, content.Length);
stream.Write(content, 0, content.Length);
}
I am getting the following output.
IP Addrress : 192.168.1.11
Waiting for client in 8001 port no
Client address : 192.168.1.11:50140
The thread '' (0x9a8) has exited with code 0 (0x0).
A first chance exception of type 'System.Net.Sockets.SocketException' occurred in System.dll
The thread '' (0x1760) has exited with code 0 (0x0).
Error in receive Data : An existing connection was forcibly closed by the remote host
The program '[1396] Window_Server.vshost.exe: Managed (v4.0.30319)' has exited with code 0 (0x0).
Please help me to fix this issue.
You need to figure out why you are throwing a socket exception. If you read the documentation for Socket.Receive You would see this section:
Note
If you receive a SocketException, use the SocketException.ErrorCode property to obtain the specific error code.
After you have obtained this code, refer to the Windows Sockets
version 2 API error code documentation in the MSDN library for a
detailed description of the error.
Follwing that link shows you how to read the error code:
The ErrorCode property contains the error code that is associated with
the error that caused the exception.
The default constructor for SocketException sets the ErrorCode
property to the last operating system error that occurred. For more
information about socket error codes, see the Windows Sockets version
2 API error code documentation in MSDN.
Which should bring you to the error codes page.
Now depending on your error code, which you have not provided, you can diagnose the network issue.
"The thread '' (0x9a8) has exited with code 0 (0x0)." is not an error. It is simply telling you that a background thread has exited. Zero means the thread ran and exited successfully.
The exception is in receiveData(object obj) as you should be able to tell, given the exception , "Error in receive Data : An existing connection was forcibly closed by the remote host".
If you post the client program you are working with I might be able to help.
The problem is that Main() does not wait for the sockets to be done with their jobs. As soon as it has created the threads, it exists... And the threads are destroyed.
You need to wait for the socket-handling threads by using events of some sort, or by sleeping, from Main() - or from MyServer(), as long as the program exists only when the whole job is done.