Catch MongoAuthenticationException in Mongo .NET 2.0 Driver - c#

I'm doing MongoDB project based on .NET 2.0 driver which involves authentication to MongoDB. There is a example code for what i'm doing:
public static bool createConneciton(string login, SecureString pass, string authDB) {
var settings = new MongoClientSettings {
Credentials = new[] {
MongoCredential.CreateCredential(authDB, login, pass)
},
Server = new MongoServerAddress("my.mongodb.server", 27017)
};
mongoClient = new MongoClient(settings);
return true;
}
if (Mongo.createConneciton(textBoxUsername.Text, pass, textBoxAuthDatabase.Text))
Task<BsonDocument> results = Mongo.getNodeStats();
public static async Task<BsonDocument> getNodeStats() {
try {
var db = Mongo.mongoClient.GetDatabase("admin");
var command = new BsonDocument {
{"serverStatus",1}
};
BsonDocument result = await db.RunCommandAsync<BsonDocument>(command).ConfigureAwait(false);
return result;
}
catch (Exception ex)
{
Logging.Log(ex);
return null;
}
}
Main problem i encountered so far is processing user's credentials. Because all operations are lazy and connection opens only on execution in getNodeStats() method. So if user types wrong credentials, he is going to wait for 30 seconds because instead of MongoDB.AuthenticationException or even MongoDB.ConnectionException method going to though only System.Timeout exception. If you look though text of exception that is quite obvious that both are rised but not catched.
"MongoDB.Driver.MongoConnectionException: An exception occurred while opening a connection to the server. ---> MongoDB.Driver.MongoAuthenticationException: Unable to authenticate using sasl protocol mechanism SCRAM-SHA-1
My first thought was to force open connection to check for credentials as soon as user typed them and hit connect button rather then waiting for any command to be executed, but apparently MongoClient class does not have .Open() method anymore. So if it does not seem to be possible i at least would like to catch AuthenticationException without need to wait for timeout, but out of ideas where should i try and catch it.

You cannot connect mongodb using MongoCredential.CreateCredential.You have to use MongoCredential.CreateMongoCRCredential method to connect the db. Because the former credential use SCRAM-SHA-1 mechanism to connect db, in .NET which will fail. And the reason I have not make clear.
Using MongoCredential.CreateMongoCRCredential, you have change "authSchema" setting in mongodb. You can refer to MongoDB-CR Authentication failed

Related

Neo4j Driver for .NET Readonly mode not working

I have problem with Neo4j Driver for .NET. To execute query, i use session with ReadOnly mode and Read transaction, but still i can modify graph via query like: Match (n) where Id(n) = 123 set n.foo = 33 return n; My code:
using (var session = Driver.Session(AccessMode.Read))
{
session.ReadTransaction(tx =>
{
try
{
var queryResult = tx.Run(job);
}
catch (Exception ex)
{
errorMessage = ex.Message;
}
});
}
Why is possible? How resolve this problem?
The AccessMode.Read define the type of the session, and this is used only when you are on a cluster mode, to perform session's transactions on a replica server and not on a core server.
It doesn't not tell that your session is a readonly one.
To have a pure read only access, you need to connect to Neo4j with a read only user.

If another request is running a method wait until finish

I'm developing an ASP.NET Web API application with C#, .NET Framework 4.7 and MongoDb.
I have this method:
[HttpPut]
[Route("api/Public/SendCommissioning/{serial}/{withChildren}")]
public HttpResponseMessage SendCommissioning(string serial, bool withChildren)
{
string errorMsg = "Cannot set commissioning.";
HttpResponseMessage response = null;
bool serverFound = true;
try
{
[...]
// Mongo
MongoHelper mgHelper = new MongoHelper();
mgHelper.InsertCommissioning(serial, withChildren);
}
catch (Exception ex)
{
_log.Error(ex.Message);
response = Request.CreateResponse(HttpStatusCode.InternalServerError);
response.ReasonPhrase = errorMsg;
}
return response;
}
Sometimes this method is called very quickly and I get an error here:
// Mongo
MongoHelper mgHelper = new MongoHelper();
mgHelper.InsertCommissioning(serial, withChildren);
Here I'm inserting the serials I received in order, and sometimes I get an error with a duplicated key in MongoDb:
I have a method to get the latest id used in Mongo (the primary key). And two requests get the same id, so when I try to insert it on Mongo I get an invalid key exception.
I thought to use a queue to store the serials and then consume them in the same order that I have received them. But I think I will get the same error when I try to store the serial in MongoDb.
Maybe if I can set a method that if it is running, I have to wait to run it, it will works. This method will have the part of insert the serials into Mongo.
How can I do that? A method that if it is running you can't run it in another Web Api request.
Or, do you know a better option?
By the way, I can't block this method. Maybe I need to run a thread with this synchronized part.

Easy tables with Xamarin Forms - InvalidOperationException

I am using this tutorial in order to connect a xamarin.forms app with easy tables. I cannot add data to the database in Azure as i get
System.InvalidOperationException
The error message is the following
An insert operation on the item is already in the queue.
The exception happends in the following line of code.
await usersTable.InsertAsync(data);
In order to add a user
var user = new User { Username = "username", Password = "password" };
bool x = await AddUser(user);
AddUser
public async Task<bool> AddUser(User user)
{
try
{
await usersTable.InsertAsync(user);
await SyncUsers();
return true;
}
catch (Exception x)
{
await new MessageDialog(x.Message.ToString()).ShowAsync();
return false;
}
}
SyncUsers()
public async Task SyncUsers()
{
await usersTable.PullAsync("users", usersTable.CreateQuery());
await client.SyncContext.PushAsync();
}
where
IMobileServiceSyncTable<User> usersTable;
MobileServiceClient client = new MobileServiceClient("url");
Initialize
var path = Path.Combine(MobileServiceClient.DefaultDatabasePath, "DBNAME.db");
var store = new MobileServiceSQLiteStore(path);
store.DefineTable<User>();
await client.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());
usersTable = client.GetSyncTable<User>();
Please check your table. You probably have added the item already. Also, I would suggest that you don't set the Id property for your entity, because you might be inserting a same ID that's already existing in your table. It's probably the reason why the exception is appearing.
Hope it helps!
Some debugging you can do:
1) Turn on diagnostic logging in the backend and debug the backend: https://adrianhall.github.io/develop-mobile-apps-with-csharp-and-azure/chapter8/developing/#debugging-your-cloud-mobile-backend
2) Add a logging delegating handler in your MobileServiceClient setup: https://adrianhall.github.io/develop-mobile-apps-with-csharp-and-azure/chapter3/server/#turning-on-diagnostic-logs
The MobileServicePushFailedException contains an inner exception that contains the actual error. Normally, it is one of the 409/412 HTTP errors, which indicates a conflict. However, it can also be a 404 (which means there is a mismatch between what your client is asking for and the table name in Easy Tables) or 500 (which means the server crashed, in which case the server-side diagnostic logs indicate why).
Easy Tables is just a Node.js service underneath the covers.

Getting "expired token" with Live SDK. Is example code correct?

I'm using the example code from http://msdn.microsoft.com/en-us/library/dn631823.aspx to perform the signing in ahead of performing any OneDrive operations. It seemed to work while I was initially coding but now that I've gone back to it after a break, any attempt to (say) read a folder gives me the error:
The access token that was provided has expired.
The code I'm using to log in is:
currentSession = null;
try
{
var authClient = new LiveAuthClient();
LiveLoginResult result = await authClient.LoginAsync(new string[] { "wl.signin", "wl.skydrive" });
if (result.Status == LiveConnectSessionStatus.Connected)
{
currentSession = result.Session;
Debug.WriteLine("... succeeeded");
}
else
Debug.WriteLine("... not connected, status is {0}", result.Status);
}
catch (LiveAuthException ex)
{
// Display an error message.
Debug.WriteLine("LiveAuthException: {0}", ex.Message);
}
catch (LiveConnectException ex)
{
// Display an error message.
Debug.WriteLine("LiveConnectException: {0}", ex.Message);
}
where currentSession is declared as a private variable in the class and it then gets used in the folder code:
LiveConnectClient liveClient = new LiveConnectClient(currentSession);
LiveOperationResult operationResult = await liveClient.GetAsync("me/skydrive");
dynamic result = operationResult.Result;
What is slightly worrying me is that the documentation says:
Create a LiveAuthClient object and call the InitializeAsync method to initialize the Live SDK. Then call the LoginAsync method with the wl.signin and wl.skydrive scopes to enable single sign-in and allow the user to access OneDrive.
but the sample code DOESN'T make any reference to InitializeAsync and there seem to be variations on the call so it isn't really clear which one (if any) I should use.
This is for a Universal App, although currently I'm just working on the WP8.1 C#/XAML part of it. I'm using Live SDK 5.6.
Thanks.
As noted in the comment I added, it looks highly likely that the "expired token" error was being caused by an incorrect date/time setting on the emulator.

Test if MongoDB server is part of a replica set at run time

I have the same software deployed in multiple environments, some use a MongoDB replica set, and some use a single server. There are certain update operations where I use WriteConcern.WMajority, but this throws an exception if the server is not part of a replica set.
I'm looking for a way to ask the server if it is part of a replica set, so I will know if it is safe to use WriteConcern.WMajority. My attempt was this:
string connStr = System.Configuration.ConfigurationManager
.ConnectionStrings["connStrName"].ConnectionString;
var server = new MongoDB.Driver.MongoClient(connStr).GetServer();
bool isReplicaSet = server.GetDatabase("admin")
.RunCommand("replSetGetStatus").Ok;
But this throws MongoDB.Driver.MongoCommandException: Command 'replSetGetStatus' failed: not running with --replSet (response: { "ok" : 0.0, "errmsg" : "not running with --replSet" }). Is catching this exception my best option?
public bool IsPartOfReplicaSet(string connectionString)
{
var result = new MongoClient(connectionString)
.GetServer()
.GetDatabase("admin")
.RunCommand("getCmdLineOpts")
.Response["parsed"] as BsonDocument;
return result.Contains("replSet");
}

Categories

Resources