Connect, log in and keep the session
Do this once at the start of every program: check that the server answers and what it supports, log in, and close the session when you are done. A long-running program also keeps its session alive.
Calls
| Step | Call | Session |
|---|---|---|
| Server version | QueryVersion | not needed |
| Server features | GetServerCapabilities | not needed |
| Log in to a vault | LogIn | creates one |
| Session and vault | GetVaultSessionInfo | needed |
| Keep the session | KeepAlive | needed |
| End the session | LogOut | needed |
QueryVersionreturns versions as one 64-bit number each: four 16-bit parts, major in the highest bits.0x001A000B41050000is 26.11.16645.0.LogInbinds the session to the vault inlogin_data.vault_guid. The response'ssession_data.session_id(48 bytes) goes into themfiles-session-id-binmetadata of every later call; the helpers do that for you. See Authentication and sessions.session_data.keep_alive_interval_in_secondsis how often to callKeepAlive(450 seconds on the server below); the server drops the session after twice that time without one. Other calls do not extend the session.- Many calls return the vault's metadata structure version in the
mfiles-metadata-version-bintrailer; the helpers keep the latest value. See Metadata structure version and caching. - After
LogOut, calls with the old session ID fail withUNAUTHENTICATED.
Code
Python
# No session is needed for these calls.
with MFilesClient.from_env(CLIENT_NAME, log_in=False) as client:
version_service = client.stub(IRPCQueryVersion_pb2_grpc.IRPCQueryVersionStub)
version = version_service.QueryVersion(IRPCQueryVersion_pb2.QueryVersionRequest())
print(f"Server version: {decode_version(version.server_version)}")
login = client.stub(IRPCLogin_pb2_grpc.IRPCLoginStub)
capabilities = login.GetServerCapabilities(
IRPCLogin_pb2.GetServerCapabilitiesRequest()).server_capabilities
print(f"Server capabilities: file_streaming={capabilities.file_streaming}, "
f"facet_search={capabilities.facet_search}")
session = client.log_in()
print(f"Logged in as {session.account_name}; "
f"keep-alive interval {session.keep_alive_interval_in_seconds} s")
info = login.GetVaultSessionInfo(
IRPCLogin_pb2.GetVaultSessionInfoRequest()).vault_session_info
print(f"Vault: {info.vault_display_name} {info.vault_guid}")
# From the trailers of the calls so far.
structure_version = client.metadata_structure_version
print(f"Metadata structure version: "
f"{'not reported' if structure_version is None else structure_version}")
# A long-running program calls KeepAlive within the keep-alive interval.
login.KeepAlive(IRPCLogin_pb2.KeepAliveRequest())
print("KeepAlive: ok")
client.log_out()
print("Logged out")
Source: python/recipes/connect.py
C#
// No session is needed for these calls.
await using var connection = MFilesConnection.Open(settings);
var versionService = new IRPCQueryVersion.IRPCQueryVersionClient(connection.CallInvoker);
var version = await versionService.QueryVersionAsync(new QueryVersionRequest());
Console.WriteLine($"Server version: {DecodeVersion(version.ServerVersion)}");
var login = new IRPCLogin.IRPCLoginClient(connection.CallInvoker);
var capabilities = (await login.GetServerCapabilitiesAsync(new GetServerCapabilitiesRequest()))
.ServerCapabilities;
Console.WriteLine($"Server capabilities: file_streaming={capabilities.FileStreaming}, " +
$"facet_search={capabilities.FacetSearch}");
var session = await connection.LogInAsync(settings, RecipeHelpers.ClientName);
Console.WriteLine($"Logged in as {session.AccountName}; " +
$"keep-alive interval {session.KeepAliveIntervalInSeconds} s");
var info = (await login.GetVaultSessionInfoAsync(new GetVaultSessionInfoRequest())).VaultSessionInfo;
Console.WriteLine($"Vault: {info.VaultDisplayName} {info.VaultGuid}");
Console.WriteLine($"Metadata structure version: {connection.MetadataStructureVersion?.ToString() ?? "not reported"}");
// A long-running program calls KeepAlive within the keep-alive interval.
await login.KeepAliveAsync(new KeepAliveRequest());
Console.WriteLine("KeepAlive: ok");
await connection.LogOutAsync();
Console.WriteLine("Logged out");
Source: csharp/Recipes/Connect.cs
Go
// Dial only creates the channel. Calls without a session work right away.
client, err := mfilesclient.Dial(cfg)
if err != nil {
return err
}
defer client.Close()
version, err := mfiles.NewIRPCQueryVersionClient(client.Conn).QueryVersion(ctx,
&mfiles.QueryVersionRequest{})
if err != nil {
return err
}
fmt.Println("Server version:", mfilesclient.VersionString(version.GetServerVersion()))
login := mfiles.NewIRPCLoginClient(client.Conn)
capabilities, err := login.GetServerCapabilities(ctx, &mfiles.GetServerCapabilitiesRequest{})
if err != nil {
return err
}
fmt.Printf("Server capabilities: file_streaming=%v, facet_search=%v\n",
capabilities.GetServerCapabilities().GetFileStreaming(),
capabilities.GetServerCapabilities().GetFacetSearch())
// Log in. From now on every call carries the session ID.
session, err := client.LogIn(ctx, cfg)
if err != nil {
return err
}
fmt.Printf("Logged in as %s; keep-alive interval %d s\n",
session.GetAccountName(), session.GetKeepAliveIntervalInSeconds())
info, err := login.GetVaultSessionInfo(ctx, &mfiles.GetVaultSessionInfoRequest{})
if err != nil {
return err
}
fmt.Printf("Vault: %s %s\n", info.GetVaultSessionInfo().GetVaultDisplayName(),
info.GetVaultSessionInfo().GetVaultGuid())
// The latest value from the mfiles-metadata-version-bin trailer of the calls so far.
if metadataStructureVersion, ok := client.MetadataStructureVersion(); ok {
fmt.Println("Metadata structure version:", metadataStructureVersion)
} else {
fmt.Println("Metadata structure version: not reported")
}
// Call KeepAlive at least every keep-alive interval on long runs; other calls do not extend
// the session.
if _, err := login.KeepAlive(ctx, &mfiles.KeepAliveRequest{}); err != nil {
return err
}
fmt.Println("KeepAlive: ok")
if err := client.LogOut(ctx); err != nil {
return err
}
fmt.Println("Logged out")
Source: go/recipes/connect/main.go
Output against an on-premises server:
Server version: 26.11.16645.0
Server capabilities: file_streaming=True, facet_search=False
Logged in as grpcdocs.user; keep-alive interval 450 s
Vault: gRPC Docs Samples {7BBEA0BC-40D8-4BCB-A67D-8A3ACFBDB575}
Metadata structure version: 1024
KeepAlive: ok
Logged out
The two capability flags are examples. file_streaming does not mean that the streaming file
transfer service can be used; see Files for the flags that matter for
uploads.
Find the vault by its name
LogIn needs the vault's GUID. A program that knows only the vault's name, or wants to let the
user pick a vault, finds the GUID first:
- LogIn with
login_data.vault_guidset to{00000000-0000-0000-0000-000000000000}. This opens a server-level session. - GetVaults with
exclude_vaults_user_cannot_accesstrue lists the vaults the user can log in to. Each hasguidanddisplay_name. - LogInWithSession with the server-level session in
mfiles-session-id-binand the chosen vault's GUID inlogin_data.vault_guidreturns a vault session, without authenticating again. Then log out the server-level session.
Python (the helper switch_to_vault does step 3):
client.config.vault = SERVER_LEVEL
client.log_in()
vaults = client.stub(IRPCVaults_pb2_grpc.IRPCVaultsStub).GetVaults(
IRPCVaults_pb2.GetVaultsRequest(exclude_vaults_user_cannot_access=True)).vaults
for vault in vaults:
print(f"{vault.display_name}: {vault.guid}")
matches = [v for v in vaults if not name or v.display_name.casefold() == name.casefold()]
if not matches:
raise SystemExit(f"No vault named '{name}' that this user can access")
session = client.switch_to_vault(matches[0].guid)
Source: python/recipes/find_vault.py
response = self.login.LogInWithSession(IRPCLogin_pb2.LogInWithSessionRequest(
client_data=self._client_data(),
login_data=structs_pb2.LoginData(server_hostname=self.config.host,
vault_guid=vault_guid)))
self.log_out() # The server-level session; the new vault session stays valid.
self.config.vault = vault_guid
self.session_id = response.session_data.session_id
self.session = response.session_data
Source: python/mfiles_client.py
See Binding the session to a vault.
Pitfalls
- The anonymous calls work without logging in, so they are the right first check of address and
TLS settings. Any call that needs a session and has none fails with
UNAUTHENTICATED, without an M-Files error stack. ServerVaultCapabilitiesflags arefalseboth when a feature is missing and when the server is older than the flag. Check the flag before you use a newer feature. See Versions and compatibility.- On M-Files Cloud, keep the
mfilesmsmcookie and send it back on every call; the helpers do. See Call metadata. - Always log out. A session that is not logged out stays on the server until it times out.
See also
- Connecting to the server, Cloud and on-premises
- Call metadata
- Quickstarts: Python, C#, Go