diff --git a/Sledgemapper.Api/Commands/BaseCommand.cs b/Sledgemapper.Api/Commands/BaseCommand.cs new file mode 100644 index 0000000..a9c3160 --- /dev/null +++ b/Sledgemapper.Api/Commands/BaseCommand.cs @@ -0,0 +1,19 @@ +using MediatR; +using System; + +namespace Sledgemapper.Api.Commands +{ + public abstract class BaseCommand : IRequest + { + public double Timestamp { get; private set; } + public string SessionName { get; private set; } + public int UserId { get; set; } + + public BaseCommand(string sessionName, int userId) + { + Timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(); + SessionName = sessionName; + UserId=userId; + } + } +} diff --git a/Sledgemapper.Api/Commands/NewSessionCommand.cs b/Sledgemapper.Api/Commands/NewSessionCommand.cs index bdd19e8..eb2d367 100644 --- a/Sledgemapper.Api/Commands/NewSessionCommand.cs +++ b/Sledgemapper.Api/Commands/NewSessionCommand.cs @@ -2,14 +2,10 @@ using MediatR; namespace Sledgemapper.Api.Commands { - public class NewSessionCommand : IRequest + public class NewSessionCommand : BaseCommand { - public string SessionName { get; set; } - public int UserId { get; } - public NewSessionCommand(string sessionName, int userId) + public NewSessionCommand(string sessionName, int userId):base(sessionName, userId) { - SessionName = sessionName; - UserId = userId; } } } \ No newline at end of file diff --git a/Sledgemapper.Api/Commands/SaveNewTileCommand.cs b/Sledgemapper.Api/Commands/SaveNewTileCommand.cs new file mode 100644 index 0000000..8e8f13e --- /dev/null +++ b/Sledgemapper.Api/Commands/SaveNewTileCommand.cs @@ -0,0 +1,47 @@ +using System.Transactions; +using System.Net.Mail; +using MediatR; +using Sledgemapper.Api.Data; +using Sledgemapper.Shared.Entities; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Sledgemapper.Api.Handlers; + +namespace Sledgemapper.Api.Commands +{ +public class SaveNewTileCommand:BaseCommand +{ + public Tile Tile {get;set;} + public SaveNewTileCommand(string sessionName, Tile tile, int userId):base(sessionName, userId){ + Tile=tile; + } +} + + public class SaveNewTileCommandHandler : IRequestHandler + { + private readonly MyDbContext _dbcontext; +private readonly IMediator _mediator; + + public SaveNewTileCommandHandler(IMediator mediator, MyDbContext dbcontext){ _dbcontext = dbcontext; _mediator= mediator;} + + public async Task Handle(SaveNewTileCommand notification, CancellationToken cancellationToken) + { + var jsonString = JsonSerializer.Serialize(notification.Tile); + + _dbcontext.MapLogs.Add(new Sledgemapper.Api.Models.MapLog + { + Operation = "N", + SessionName = notification.SessionName, + Type = "T", + Timestamp = notification.Timestamp, + Object = jsonString + }); + await _dbcontext.SaveChangesAsync(); + await _mediator.Publish(new NewTileNotification(notification.SessionName, notification.Tile)); + return true; + } + + + } +} diff --git a/Sledgemapper.Api/Controllers/SessionController.cs b/Sledgemapper.Api/Controllers/SessionController.cs index 43ef61b..9f6352e 100644 --- a/Sledgemapper.Api/Controllers/SessionController.cs +++ b/Sledgemapper.Api/Controllers/SessionController.cs @@ -1,3 +1,4 @@ +using System.Net; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -17,48 +18,50 @@ namespace Sledgemapper.Api.Controllers public SessionController(IMediator mediator) { _mediator = mediator; } [HttpPost] - public async Task Post(string sessionName) + public async Task Post(string sessionName) { var userId = int.Parse(HttpContext.User.Identity.Name); - var result = await _mediator.Send(new NewSessionCommand(sessionName, userId)); - - } + return result; + } [HttpPost("tile")] - public async Task Post(string sessionName, [FromBody]Tile tile) + public async Task Post(string sessionName, [FromBody] Tile tile) { - await _mediator.Publish(new NewTileNotification(sessionName, tile)); + var userId = int.Parse(HttpContext.User.Identity.Name); + await _mediator.Send(new SaveNewTileCommand(sessionName, tile, userId)); } [HttpPost("overlay")] - public async Task Post(string sessionName, [FromBody]Overlay overlay) + public async Task Post(string sessionName, [FromBody] Overlay overlay) { await _mediator.Publish(new NewOverlayNotification(sessionName, overlay)); } - [HttpPost("wall")] - public async Task Post(string sessionName, [FromBody]Wall wall) + [HttpPost("wall")] + public async Task Post(string sessionName, [FromBody] Wall wall) { await _mediator.Publish(new NewWallNotification(sessionName, wall)); } - [HttpDelete("tile")] - public async Task Delete(string sessionName, [FromBody]Tile tile) + [HttpDelete("tile")] + public async Task Delete(string sessionName, [FromBody] Tile tile) { await _mediator.Publish(new DeleteTileNotification(sessionName, tile)); } [HttpDelete("overlay")] - public async Task Delete(string sessionName, [FromBody]Overlay overlay) + public async Task Delete(string sessionName, [FromBody] Overlay overlay) { await _mediator.Publish(new DeleteOverlayNotification(sessionName, overlay)); } - [HttpDelete("wall")] - public async Task Delete(string sessionName, [FromBody]Wall wall) + [HttpDelete("wall")] + public async Task Delete(string sessionName, [FromBody] Wall wall) { await _mediator.Publish(new DeleteWallNotification(sessionName, wall)); } + + } } \ No newline at end of file diff --git a/Sledgemapper.Api/Data/MyDbContext.cs b/Sledgemapper.Api/Data/MyDbContext.cs index 7040458..653eda4 100644 --- a/Sledgemapper.Api/Data/MyDbContext.cs +++ b/Sledgemapper.Api/Data/MyDbContext.cs @@ -13,30 +13,30 @@ namespace Sledgemapper.Api.Data } } - - - public class MyDbContext : DbContext { public DbSet MapLogs { get; set; } + public DbSet Sessions { get; set; } + public DbSet UserConnections { get; set; } + public DbSet SessionUsers { get; set; } public MyDbContext(DbContextOptions options) : base(options) { - + } - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - // optionsBuilder. - // options.MigrationsAssembly(Assembly.GetExecutingAssembly().FullName); - // optionsBuilder.UseSqlite("Filename=SledgemapperDatabase.db", options => - // { - // options.MigrationsAssembly(Assembly.GetExecutingAssembly().FullName); - // }); - optionsBuilder.UseSqlite("Filename=MyDatabase.db").UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); + // protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + // { + // // optionsBuilder. + // // options.MigrationsAssembly(Assembly.GetExecutingAssembly().FullName); + // // optionsBuilder.UseSqlite("Filename=SledgemapperDatabase.db", options => + // // { + // // options.MigrationsAssembly(Assembly.GetExecutingAssembly().FullName); + // // }); + // optionsBuilder.UseSqlite("Filename=MyDatabase.db").UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); - base.OnConfiguring(optionsBuilder); - } + // base.OnConfiguring(optionsBuilder); + // } protected override void OnModelCreating(ModelBuilder modelBuilder) { @@ -45,8 +45,28 @@ namespace Sledgemapper.Api.Data modelBuilder.Entity(entity => { entity.HasKey(e => e.MapLogId); - //entity.HasIndex(e => {e.SessionName, e.Timestamp}); - }); + }); + + modelBuilder.Entity().ToTable("Session", "dbo"); + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.SessionId); + entity.HasIndex(e => e.SessionName).IsUnique(); + }); + + + modelBuilder.Entity().ToTable("UserConnection", "dbo"); + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.UserConnectionId); + }); + + modelBuilder.Entity().ToTable("SessionUser", "dbo"); + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.SessionUserId); + }); + base.OnModelCreating(modelBuilder); } } diff --git a/Sledgemapper.Api/Handlers/StartNewSessionHandler.cs b/Sledgemapper.Api/Handlers/StartNewSessionHandler.cs index df125d6..211b019 100644 --- a/Sledgemapper.Api/Handlers/StartNewSessionHandler.cs +++ b/Sledgemapper.Api/Handlers/StartNewSessionHandler.cs @@ -20,11 +20,11 @@ namespace Sledgemapper.Api.Handlers public async Task Handle(NewSessionCommand notification, CancellationToken cancellationToken) { - // _dbcontext.MapLogs.Add(new Session - // { - // SessionName = notification.SessionName, - // OwnerUserId = notification.UserId - // }); + _dbcontext.Sessions.Add(new Session + { + SessionName = notification.SessionName, + OwnerUserId = notification.UserId + }); await _dbcontext.SaveChangesAsync(); return true; } diff --git a/Sledgemapper.Api/Hubs/SledgemapperHub.cs b/Sledgemapper.Api/Hubs/SledgemapperHub.cs index 90824ad..d60ce11 100644 --- a/Sledgemapper.Api/Hubs/SledgemapperHub.cs +++ b/Sledgemapper.Api/Hubs/SledgemapperHub.cs @@ -12,6 +12,8 @@ using Sledgemapper.Api.Data; using System.Text.Json; using System.Text.Json.Serialization; using Microsoft.AspNetCore.Authorization; +using Sledgemapper.Api.Models; +using Sledgemapper.Helpers; namespace SignalRChat.Hubs { @@ -20,11 +22,15 @@ namespace SignalRChat.Hubs [Authorize] public class SledgemapperHub : Hub { - public SledgemapperHub() - { + private readonly MyDbContext _dbContext; + private readonly DataContext _datacontext; + public SledgemapperHub(MyDbContext dbContext, DataContext datacontext) + { + _dbContext = dbContext; + _datacontext = datacontext; } - private static Dictionary _sessions = new Dictionary(); + // private static Dictionary _sessions = new Dictionary(); public List Colors = new List{"CC0000", "CC3300", "FFCC00", @@ -114,60 +120,116 @@ namespace SignalRChat.Hubs await Clients.Group(sessionName).DeleteOverlay(tile); } - public async Task NewSession(string sessionName, string initials) + // public async Task NewSession(string sessionName, string initials) + // { + // var userId = int.Parse(Context.User.Identity.Name); + + // // var user = this.Context.GetHttpContext().; + // var session = new Session(); + // session.Colors = new List(Colors); + // session.Colors.Shuffle(); + // var player = new Player { Position = new Tile { X = 0, Y = 0 }, ConnectionId = Context.ConnectionId, Color = session.Colors[0], Initials = initials }; + // session.Players.Add(player); + // _sessions.Add(sessionName, session); + + + // await Groups.AddToGroupAsync(Context.ConnectionId, sessionName); + // return session; + // } + + public async Task JoinSession(string sessionName, string initials) { - + var session = _dbContext.Sessions.FirstOrDefault(s => s.SessionName == sessionName); var userId = int.Parse(Context.User.Identity.Name); - // var user = this.Context.GetHttpContext().; - var session = new Session(); - session.Colors = new List(Colors); - session.Colors.Shuffle(); - var player = new Player { Position = new Tile { X = 0, Y = 0 }, ConnectionId = Context.ConnectionId, Color = session.Colors[0], Initials = initials }; - session.Players.Add(player); - _sessions.Add(sessionName, session); - - - await Groups.AddToGroupAsync(Context.ConnectionId, sessionName); - return session; - } - - public async Task JoinSession(string sessionName, string initials) - { - if (_sessions.ContainsKey(sessionName)) + if (session != null) { - var session = _sessions[sessionName]; - var player = new Player { Position = new Tile { X = 0, Y = 0 }, ConnectionId = Context.ConnectionId, Color = session.Colors[session.Players.Count], Initials = initials }; - session.Players.Add(player); - await Clients.Group(sessionName).NewPlayer(player); + // var newSession = new Session(); + var userSession = new SessionUser { SessionId = session.SessionId, UserId = userId }; + _dbContext.SessionUsers.Add(userSession); + await _dbContext.SaveChangesAsync(); + var usersSession = _dbContext.SessionUsers.Where(m => m.SessionId == session.SessionId).Select(m => m.UserId).ToList(); + var players = _datacontext. + Users. + Where(m => usersSession.Contains(m.Id)). + Select(p => new Player + { + Initials = p.Initials, + UserId = userId, + Position = new Tile { X = 0, Y = 0 } + }).ToList(); + await _dbContext.SaveChangesAsync(); + await Groups.AddToGroupAsync(Context.ConnectionId, sessionName); - return session; + var newSession = new Sledgemapper.Shared.Entities.Session + { + Players = players, + SessionName = sessionName + }; + + return newSession; } else { return null; } + + // if (_sessions.ContainsKey(sessionName)) + // { + // var session = _sessions[sessionName]; + // var player = new Player { Position = new Tile { X = 0, Y = 0 }, ConnectionId = Context.ConnectionId, Color = session.Colors[session.Players.Count], Initials = initials }; + // session.Players.Add(player); + // await Clients.Group(sessionName).NewPlayer(player); + // return session; + // } + // else + // { + // return null; + // } } public async Task UpdatePosition(string sessionName, Tile tile) { - var player = _sessions[sessionName].Players.First(m => m.ConnectionId == Context.ConnectionId); - player.Position = tile; - await Clients.Group(sessionName).PlayerUpdate(player); + // var userId = int.Parse(Context.User.Identity.Name); + // var session = _dbContext.Sessions.FirstOrDefault(m => m.SessionName == sessionName); + + // var player = _sessions[sessionName].Players.First(m => m.ConnectionId == Context.ConnectionId); + // player.Position = tile; + // await Clients.Group(sessionName).PlayerUpdate(player); } - public async Task Refresh(string sessionName) + // public async Task Refresh(string sessionName) + // { + // return _sessions[sessionName]; + // } + + // public async Task Sync(string sessionName, Session map) + // { + // _sessions[sessionName].Map = map.Map; + // _sessions[sessionName].Overlays = map.Overlays; + // _sessions[sessionName].Walls = map.Walls; + + // await Clients.Group(sessionName).UpdateMap(_sessions[sessionName]); + // } + + + + public override async Task OnConnectedAsync() { - return _sessions[sessionName]; + var userId = int.Parse(Context.User.Identity.Name); + //var result = _connectedPlayers.AddOrUpdate(Context.ConnectionId, userId,(key, oldValue) => userId); + var userConnection = new UserConnection { ConnectionId = Context.ConnectionId, UserId = userId }; + _dbContext.UserConnections.Add(userConnection); + await _dbContext.SaveChangesAsync(); + await base.OnConnectedAsync(); } - public async Task Sync(string sessionName, Session map) + public override Task OnDisconnectedAsync(Exception exception) { - _sessions[sessionName].Map = map.Map; - _sessions[sessionName].Overlays = map.Overlays; - _sessions[sessionName].Walls = map.Walls; - - await Clients.Group(sessionName).UpdateMap(_sessions[sessionName]); + _connectedPlayers.TryRemove(Context.ConnectionId, out var userId); + return base.OnDisconnectedAsync(exception); } + + ConcurrentDictionary _connectedPlayers = new ConcurrentDictionary(); } } \ No newline at end of file diff --git a/Sledgemapper.Api/LocalDatabase.db b/Sledgemapper.Api/LocalDatabase.db new file mode 100644 index 0000000..20954d8 Binary files /dev/null and b/Sledgemapper.Api/LocalDatabase.db differ diff --git a/Sledgemapper.Api/Models/Session.cs b/Sledgemapper.Api/Models/Session.cs index 8416f42..3876fcc 100644 --- a/Sledgemapper.Api/Models/Session.cs +++ b/Sledgemapper.Api/Models/Session.cs @@ -1,3 +1,4 @@ +using System.Data; using System; using System.ComponentModel.DataAnnotations; diff --git a/Sledgemapper.Api/Models/SessionUser.cs b/Sledgemapper.Api/Models/SessionUser.cs new file mode 100644 index 0000000..a91a67c --- /dev/null +++ b/Sledgemapper.Api/Models/SessionUser.cs @@ -0,0 +1,18 @@ +using System.Data; +using System; +using System.ComponentModel.DataAnnotations; + +namespace Sledgemapper.Api.Models +{ + public class SessionUser + { + [Key] + public int SessionUserId { get; set; } + + [Required] + public int SessionId { get; set; } + + [Required] + public int UserId { get; set; } + } +} diff --git a/Sledgemapper.Api/Models/UserConnection.cs b/Sledgemapper.Api/Models/UserConnection.cs new file mode 100644 index 0000000..4586c0d --- /dev/null +++ b/Sledgemapper.Api/Models/UserConnection.cs @@ -0,0 +1,17 @@ +using System.Data; +using System; +using System.ComponentModel.DataAnnotations; + +namespace Sledgemapper.Api.Models +{ + public class UserConnection + { + [Key] + public int UserConnectionId { get; set; } + [Required] + public int UserId { get; set; } + + [Required] + public string ConnectionId{get;set;} + } +} diff --git a/Sledgemapper.Api/Program.cs b/Sledgemapper.Api/Program.cs index 1faa5d3..b7f86b8 100644 --- a/Sledgemapper.Api/Program.cs +++ b/Sledgemapper.Api/Program.cs @@ -15,7 +15,9 @@ namespace SignalRChat { public static void Main(string[] args) { - CreateHostBuilder(args).Build().Run(); + var host= CreateHostBuilder(args).Build(); + CreateDbIfNotExists(host); + host.Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => @@ -32,22 +34,22 @@ namespace SignalRChat // webBuilder.UseStartup(); // }); - // private static void CreateDbIfNotExists(IHost host) - // { - // using (var scope = host.Services.CreateScope()) - // { - // var services = scope.ServiceProvider; - // try - // { - // var context = services.GetRequiredService(); - // DbInitializer.Initialize(context); - // } - // catch (Exception ex) - // { - // var logger = services.GetRequiredService>(); - // logger.LogError(ex, "An error occurred creating the DB."); - // } - // } - // } + private static void CreateDbIfNotExists(IHost host) + { + using (var scope = host.Services.CreateScope()) + { + var services = scope.ServiceProvider; + try + { + var context = services.GetRequiredService(); + DbInitializer.Initialize(context); + } + catch (Exception ex) + { + var logger = services.GetRequiredService>(); + logger.LogError(ex, "An error occurred creating the DB."); + } + } + } } } diff --git a/Sledgemapper.Api/sledgemapper.db b/Sledgemapper.Api/sledgemapper.db new file mode 100644 index 0000000..9846409 Binary files /dev/null and b/Sledgemapper.Api/sledgemapper.db differ diff --git a/Sledgemapper.Shared/Entities/Player.cs b/Sledgemapper.Shared/Entities/Player.cs index 4c70497..976d516 100644 --- a/Sledgemapper.Shared/Entities/Player.cs +++ b/Sledgemapper.Shared/Entities/Player.cs @@ -2,7 +2,7 @@ namespace Sledgemapper.Shared.Entities { public class Player { - public string ConnectionId { get; set; } + public int UserId { get; set; } public string Color { get; set; } public string Initials { get; set; } diff --git a/Sledgemapper/CommunicationManager.cs b/Sledgemapper/CommunicationManager.cs index d94bb00..7e889de 100644 --- a/Sledgemapper/CommunicationManager.cs +++ b/Sledgemapper/CommunicationManager.cs @@ -7,6 +7,8 @@ using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading; using System.Threading.Tasks; namespace Sledgemapper @@ -26,7 +28,7 @@ namespace Sledgemapper .WithAutomaticReconnect() .WithUrl("http://localhost:5000/SledgemapperHub", options => - { + { options.AccessTokenProvider = () => Task.FromResult(_authenticateResponse.Token); }) @@ -35,16 +37,8 @@ namespace Sledgemapper - var httpClientHandler = new HttpClientHandler(); - - //if (myConfigurationService.VerifySslCertificate == false) - //{ - httpClientHandler.ServerCertificateCustomValidationCallback = - (message, certificate, chain, sslPolicyErrors) => true; - //} - Api = RestService.For( - new HttpClient(httpClientHandler) + new HttpClient(new AuthenticatedHttpClientHandler(GetToken)) { BaseAddress = new Uri("http://localhost:5000") } @@ -59,7 +53,7 @@ namespace Sledgemapper Connection.On("PlayerUpdate", (player) => { - var p = SessionData.Players.FirstOrDefault(m => m.ConnectionId == player.ConnectionId); + var p = SessionData.Players.FirstOrDefault(m => m.UserId == player.UserId); if (p != null) { p.Position = player.Position; @@ -101,7 +95,7 @@ namespace Sledgemapper Connection.On("NewPlayer", (player) => { - var p = SessionData.Players.FirstOrDefault(m => m.ConnectionId == player.ConnectionId); + var p = SessionData.Players.FirstOrDefault(m => m.UserId == player.UserId); if (p is null) { SessionData.Players.Add(player); @@ -114,6 +108,11 @@ namespace Sledgemapper }); } + private Task GetToken() + { + return Task.FromResult(_authenticateResponse.Token); + } + public async Task Register(RegisterModel registerModel) { var result = await Api.Register(registerModel); @@ -173,4 +172,34 @@ namespace Sledgemapper } } + + class AuthenticatedHttpClientHandler : HttpClientHandler + { + private readonly Func> getToken; + + public AuthenticatedHttpClientHandler(Func> getToken) + { + if (getToken == null) throw new ArgumentNullException(nameof(getToken)); + this.getToken = getToken; + + //if (myConfigurationService.VerifySslCertificate == false) + //{ + ServerCertificateCustomValidationCallback = + (message, certificate, chain, sslPolicyErrors) => true; + //} + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + // See if the request has an authorize header + var auth = request.Headers.Authorization; + if (auth != null) + { + var token = await getToken().ConfigureAwait(false); + request.Headers.Authorization = new AuthenticationHeaderValue(auth.Scheme, token); + } + + return await base.SendAsync(request, cancellationToken).ConfigureAwait(false); + } + } } diff --git a/Sledgemapper/IMapApi.cs b/Sledgemapper/IMapApi.cs index 01af572..eafac08 100644 --- a/Sledgemapper/IMapApi.cs +++ b/Sledgemapper/IMapApi.cs @@ -9,8 +9,12 @@ using System.Threading.Tasks; namespace Sledgemapper { + [Headers("Authorization: Bearer")] public interface IMapApi { + [Post("/session/{sessionName}")] + Task NewSession(string sessionName); + [Post("/session/{sessionName}/tile")] Task NewTile([Body] Tile tile, string sessionName); @@ -28,10 +32,13 @@ namespace Sledgemapper [Delete("/session/{sessionName}/overlay")] Task DeleteOverlay([Body] Overlay overlay, string sessionName); - + + + [Headers("Authorization")] [Post("/users/register")] Task Register([Body] RegisterModel registerModel); + [Headers("Authorization")] [Post("/users/authenticate")] Task Authenticate([Body] AuthenticateModel registerModel); } diff --git a/Sledgemapper/Sledgemapper.cs b/Sledgemapper/Sledgemapper.cs index e660503..80072b2 100644 --- a/Sledgemapper/Sledgemapper.cs +++ b/Sledgemapper/Sledgemapper.cs @@ -473,16 +473,21 @@ namespace Sledgemapper var successful = false; try { - var session = await _communicationManager.Connection?.InvokeAsync("NewSession", localContent.TxtSession.Text, _authResponse.Initials); - if (session != null) + var result = await _communicationManager.Api.NewSession(localContent.TxtSession.Text); + + // var session = await _communicationManager.Connection?.InvokeAsync("NewSession", localContent.TxtSession.Text, _authResponse.Initials); + if (result) { - _sessionData = session; + //_sessionData; _sessionData.SessionName = localContent.TxtSession.Text; + _sessionData.MapEntityAdded -= OnMapEntityAdded; _sessionData.MapEntityAdded += OnMapEntityAdded; - _sessionData.Players = session.Players; + // _sessionData.Players = session.Players; } - successful = session != null; + successful = result; + var result2 = await _communicationManager.Connection?.InvokeAsync("JoinSession", localContent.TxtSession.Text, _authResponse.Initials); + } catch (Exception ex) {