diff --git a/Realm/Realm/Handles/AppHandle.cs b/Realm/Realm/Handles/AppHandle.cs
index a7e8f89a39..2a4746cc3e 100644
--- a/Realm/Realm/Handles/AppHandle.cs
+++ b/Realm/Realm/Handles/AppHandle.cs
@@ -349,13 +349,13 @@ public Uri GetBaseUri()
return new Uri(uriString);
}
- public async Task UpdateBaseUriAsync(Uri newUri)
+ public async Task UpdateBaseUriAsync(Uri? newUri)
{
var tcs = new TaskCompletionSource();
var tcsHandle = GCHandle.Alloc(tcs);
try
{
- var url = newUri.ToString();
+ var url = newUri?.ToString().TrimEnd('/') ?? string.Empty;
NativeMethods.update_base_uri(this, url, (IntPtr)url.Length, GCHandle.ToIntPtr(tcsHandle), out var ex);
ex.ThrowIfNecessary();
await tcs.Task;
diff --git a/Realm/Realm/Sync/App.cs b/Realm/Realm/Sync/App.cs
index 98a8f4edec..88036677bc 100644
--- a/Realm/Realm/Sync/App.cs
+++ b/Realm/Realm/Sync/App.cs
@@ -275,7 +275,10 @@ public Task DeleteUserFromServerAsync(User user)
/// Temporarily overrides the value from
/// with a new value used for communicating with the server.
///
- /// The new uri that will be used for communicating with the server.
+ ///
+ /// The new uri that will be used for communicating with the server. If set to null, the base uri will
+ /// be reset to its default value.
+ ///
/// An awaitable that represents the asynchronous operation.
///
/// The App will revert to using the value in [AppConfiguration] when it is restarted.
@@ -287,7 +290,7 @@ public Task DeleteUserFromServerAsync(User user)
/// This API is experimental and subject to change without a major version increase.
///
[Experimental("Rlm001", UrlFormat = "www.mongodb.com/docs/atlas/app-services/edge-server/connect/#roaming-between-edge-servers")]
- public Task UpdateBaseUriAsync(Uri newUri) => Handle.UpdateBaseUriAsync(newUri);
+ public Task UpdateBaseUriAsync(Uri? newUri) => Handle.UpdateBaseUriAsync(newUri);
///
public override bool Equals(object? obj)
diff --git a/Tests/Realm.Tests/Sync/AppTests.cs b/Tests/Realm.Tests/Sync/AppTests.cs
index 72f3d3cfb1..3ee2ec1620 100644
--- a/Tests/Realm.Tests/Sync/AppTests.cs
+++ b/Tests/Realm.Tests/Sync/AppTests.cs
@@ -401,7 +401,7 @@ public void RealmConfigurationBaseUrl_ReturnsExpectedValue()
}
[Test]
- public void App_ChangeBaseUri_UpdatesBaseUri()
+ public void App_UpdateBaseUri_UpdatesBaseUri()
{
SyncTestHelpers.RunBaasTestAsync(async () =>
{
@@ -411,12 +411,32 @@ public void App_ChangeBaseUri_UpdatesBaseUri()
Assert.That(app.BaseUri, Is.EqualTo(new Uri("https://services.mongodb.com")));
-#pragma warning disable RLM001
+#pragma warning disable Rlm001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
await app.UpdateBaseUriAsync(SyncTestHelpers.BaasUri!);
-#pragma warning restore RLM001
+#pragma warning restore Rlm001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
Assert.That(app.BaseUri, Is.EqualTo(SyncTestHelpers.BaasUri));
});
}
+
+ [Test]
+ public void App_UpdateBaseUri_WhenUnreachable_Throws()
+ {
+ SyncTestHelpers.RunBaasTestAsync(async () =>
+ {
+ var appConfig = SyncTestHelpers.GetAppConfig(AppConfigType.FlexibleSync);
+ appConfig.BaseUri = new Uri("https://services.mongodb.com");
+ var app = App.Create(appConfig);
+
+ Assert.That(app.BaseUri, Is.EqualTo(new Uri("https://services.mongodb.com")));
+
+#pragma warning disable Rlm001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+ var ex = await TestHelpers.AssertThrows(() => app.UpdateBaseUriAsync(new Uri("https://google.com")));
+#pragma warning restore Rlm001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+
+ Assert.That(ex.Message, Does.Contain("404"));
+ Assert.That(ex.StatusCode, Is.EqualTo(HttpStatusCode.NotFound));
+ });
+ }
}
}
diff --git a/wrappers/src/app_cs.cpp b/wrappers/src/app_cs.cpp
index 90fe1e144c..ccf3f694d1 100644
--- a/wrappers/src/app_cs.cpp
+++ b/wrappers/src/app_cs.cpp
@@ -347,6 +347,25 @@ extern "C" {
});
}
+ REALM_EXPORT void shared_app_update_base_url(SharedApp& app, uint16_t* url_buf, size_t url_len, void* tcs_ptr, NativeException::Marshallable& ex)
+ {
+ return handle_errors(ex, [&]() {
+ std::string url(Utf16StringAccessor(url_buf, url_len));
+
+ app->update_base_url(url, [tcs_ptr](util::Optional err) {
+ if (err) {
+ auto& err_copy = *err;
+ MarshaledAppError app_error(err_copy);
+
+ s_void_callback(tcs_ptr, app_error);
+ }
+ else {
+ s_void_callback(tcs_ptr, MarshaledAppError());
+ }
+ });
+ });
+ }
+
#pragma region EmailPassword
REALM_EXPORT void shared_app_email_register_user(SharedApp& app, uint16_t* username_buf, size_t username_len, uint16_t* password_buf, size_t password_len, void* tcs_ptr, NativeException::Marshallable& ex)