I want to make SignalR connection establishment when login to system,now it's doing separately.In .net core I used Microsoft.AspNetCore.SignalR package and in angular I used @aspnet/signalr.When user connect with signalR,then that user want to store in a list with connectionId and username.
Here is my login method in client side
login(model: any) {
return this.http.post(this.baseUrl + 'login', model).pipe(
map((response: any) => {
const user = response;
if (user) {
localStorage.setItem('token', user.token);
localStorage.setItem('user', JSON.stringify(user.user));
localStorage.setItem('role', user.roles[0]);
this.currentUser = user.user;
this.decodedToken = this.jwtHelper.decodeToken(user.token);
this.userRole = user.roles[0];
this.changeMemberPhoto(this.currentUser.photoUrl);
}
})
);
}
this is server side login method
[HttpPost("login")]
public async Task<IActionResult> Login(UserForLoginDto userForLoginDto)
{
try
{
var loggedUser = await _userManager.FindByNameAsync(userForLoginDto.Username);
var result = await _signInManager.CheckPasswordSignInAsync(loggedUser, userForLoginDto.Password, false);
if (result.Succeeded)
{
var appUser = await _userManager.Users.Include(p => p.Photos).Include(r => r.UserRoles)
.FirstOrDefaultAsync(u => u.NormalizedUserName == userForLoginDto.Username.ToUpper());
var selectedUser = await _userManager.FindByNameAsync(appUser.UserName);
// Get the roles for the user
var roles = await _userManager.GetRolesAsync(selectedUser);
var userToReturn = _mapper.Map<UserForListDto>(appUser);
var generatedToken = GenerateJwtToken(appUser);
return Ok(new
{
token = generatedToken.Result,
user = userToReturn,
roles = roles
});
}
return Unauthorized();
}
catch (Exception e)
{
return BadRequest("An error occurs while loggin:" + e.ToString());
}
}
private async Task<string> GenerateJwtToken(User user)
{
var claims = new List<Claim> {
new Claim(ClaimTypes.NameIdentifier,user.Id.ToString()),
new Claim(ClaimTypes.Name, user.UserName)
};
var roles = await _userManager.GetRolesAsync(user);
foreach (var role in roles)
{
claims.Add(new Claim(ClaimTypes.Role, role));
}
var key = new SymmetricSecurityKey(Encoding.UTF8
.GetBytes(_config.GetSection("AppSettings:Token").Value));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);
var tokenDescripter = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.Now.AddDays(1),
SigningCredentials = creds
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescripter);
return tokenHandler.WriteToken(token);
}
this is my startup class code
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DataContext>(s => s.UseMySql(Configuration.GetConnectionString("DefaultConnection"))
.ConfigureWarnings(warnings => warnings.Ignore(CoreEventId.IncludeIgnoredWarning)));
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
policy => policy.AllowAnyMethod()
.AllowAnyHeader()
.WithOrigins("http://localhost:4200")
.AllowCredentials());
});
services.AddSignalR();
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddJsonOptions(opt =>
{
opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
services.AddAutoMapper();
services.AddTransient<Seed>();
services.AddScoped<IAuthRepository, AuthRepository>();
services.AddScoped<IDatingRepository, DatingRepository>();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII
.GetBytes(Configuration.GetSection("AppSettings:Token").Value)),
ValidateIssuer = false,
ValidateAudience = false
};
});
services.AddScoped<LogUserActivity>();
IdentityBuilder builder = services.AddIdentityCore<User>(opt =>
{
opt.Password.RequireDigit = false;
opt.Password.RequiredLength = 4;
opt.Password.RequireNonAlphanumeric = false;
opt.Password.RequireUppercase = false;
});
builder = new IdentityBuilder(builder.UserType, typeof(Role), builder.Services);
builder.AddEntityFrameworkStores<DataContext>();
builder.AddRoleValidator<RoleValidator<Role>>();
builder.AddRoleManager<RoleManager<Role>>();
builder.AddSignInManager<SignInManager<User>>();
// services.AddAuthorization(options => {
// options.AddPolicy("RequireAdminRole", policy => policy.RequireRole("Admin"));
// options.AddPolicy("SuperAdminPhotoRole", policy => policy.RequireRole("SuperAdmin"));
// });
// services.AddCors();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, Seed seeder, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"))
.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler(builder =>
{
builder.Run(async context =>
{
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
var error = context.Features.Get<IExceptionHandlerFeature>();
if (error != null)
{
context.Response.AddApplicationError(error.Error.Message);
await context.Response.WriteAsync(error.Error.Message);
}
});
});
// app.UseHsts();
}
// app.UseHttpsRedirection();
seeder.SeedUsers();
app.UseCors("CorsPolicy");
//app.UseCors(x => x.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
app.UseSignalR(routes =>
{
routes.MapHub<MessageHub>("/hub");
});
app.UseAuthentication();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Fallback", action = "Index" }
);
});
}
}
This is the code for SignalR in client side
export class HubconnectionService {
_hubConnection: HubConnection;
baseUrl = environment.apiUrl;
constructor() {
this._hubConnection = new HubConnectionBuilder()
.withUrl(this.baseUrl + 'hub')
.build();
}
public startConnection() {
this._hubConnection.start().catch(err => document.write(err));
}
}
here is my Hub class in .net core
public class MessageHub : Hub
{
List<UserConnection> uList = new List<UserConnection>();
public async Task NewMessage(string username, string message)
{
var user = uList.Where(o => o.UserName == username);
if (user.Any())
{
await Clients.Client(user.First().ConnectionID).SendAsync("messageReceived", username, message);
}
}
public override async Task OnConnectedAsync()
{
string name = Context.User.Identity.Name;
var us = new UserConnection();
us.UserName = name;
us.ConnectionID = Context.ConnectionId;
uList.Add(us);
await base.OnConnectedAsync();
}
}
please help me