Всем здравствуйте, и так, есть чат переписки в приложении ASP.NET Core + Angular 8, суть проблемы в том, что когда переписываются между собой 2 пользователя, то все идет как надо, но если первый пользователь отправляет сообщение второму пользователю, а второй пользователь в этот момент находится в чате с третьим, то он все равно видит сообщение от первого пользователя... Надеюсь вы поняли эту цепочку. Как бы логика программы понятна, ведь сообщения от первого пользователя направлены второму, и по этому они появляются, но как сделать так, чтобы сообщения ограничивались одним чатом, т.е. первый пользователь пишет второму, а второй пока не зайдет в чат к первому, не будет получать сообщения? Бежим по коду: Сам чат на сервере:
public class ChatHub : Hub
{
[Authorize]
public async Task SendToAll(string name, string message, string to)
{
var userName = Context.User.Identity.Name;
if (Context.UserIdentifier != to) // если получатель и текущий пользователь не совпадают
await Clients.User(userName).SendAsync("Receive", name, message);
await Clients.User(to).SendAsync("Receive", name, message);
}
}
Провайдер:
public class CustomUserIdProvider : IUserIdProvider
{
public virtual string GetUserId(HubConnectionContext connection)
{
return connection.User?.Identity.Name;
// или так
//return connection.User?.FindFirst(ClaimTypes.Name)?.Value;
}
}
Метод конфигурации стартапа
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IUserIdProvider, CustomUserIdProvider>();
services.AddSignalR();
services.AddCors(options =>
{
options.AddPolicy("EnableCORS", builder =>
{
builder.
AllowAnyOrigin().
AllowAnyHeader().
AllowAnyMethod().
WithOrigins("http://localhost:4200").
AllowCredentials();
});
});
services.AddScoped<DBUserContext>();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "http://localhost:5000",
ValidAudience = "http://localhost:5000",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("superSecretKey@345"))
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
// если запрос направлен хабу
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) &&
(path.StartsWithSegments("/chat")))
{
// получаем токен из строки запроса
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});
Компонент в ангуляре:
export class ChatComponent implements OnInit {
constructor(private http: HttpClient, activeRoute: ActivatedRoute) {
this.id = Number.parseInt(activeRoute.snapshot.params["id"]);
}
private _hubConnection: HubConnection;
user: User;
id: number;
userForMessage: User;
message:string = '';
messages: string[] = [];
bool: boolean = false;
public sendMessage(): void {
this._hubConnection
.invoke('SendToAll', this.user.userName, this.message, this.userForMessage.userName)
.then(() => this.message = '')
.catch(err => console.error(err));
this.save();
}
ngOnInit() {
//this.nick = window.prompt('Your name:', 'John');
let token = localStorage.getItem("jwt");
//Получаем юзера, которому отправляем сообщение
this.http.get(`http://localhost:5000/api/user/getuserformessage/${this.id}`
).subscribe((response: User) => {
this.userForMessage = response;
}, err => {
console.log(err)
});
//Юзер который отправляет сообщение
this.http.get("http://localhost:5000/api/customers/getidenti", {
headers: new HttpHeaders({
"Authorization": "Bearer " + token,
"Content-Type": "application/json"
})
}).subscribe((response: User) => {
this.user = response;
this.getmessages();
}, err => {
console.log(err)
});
let hubUrl = 'http://localhost:5000/chat';
this._hubConnection = new signalR.HubConnectionBuilder()
.withUrl(hubUrl, { accessTokenFactory: () => token })
.build();
this._hubConnection
.start()
.then(() => console.log('Connection started!'))
.catch(err => console.log('Error while establishing connection :('));
this._hubConnection.on('Receive', (nick: string, receivedMessage: string) => {
const text = `${nick}: ${receivedMessage}`;
this.messages.push(text);
});
}
public save() {
let token = localStorage.getItem("jwt");
this.http.get(`http://localhost:5000/api/messages/sevemessage/${this.id}/${this.message}`, {
headers: new HttpHeaders({
"Authorization": "Bearer " + token,
"Content-Type": "application/json"
})
}).subscribe(err => {
console.log(err)
});
}
public getmessages() {
let token = localStorage.getItem("jwt");
this.http.get(`http://localhost:5000/api/messages/GetMessages/${this.user.id}/${this.userForMessage.id}`, {
headers: new HttpHeaders({
"Authorization": "Bearer " + token,
"Content-Type": "application/json"
})
}).subscribe((response: string[]) => {
this.messages = response;
}, err => {
console.log(err)
});
}
}
И HTML Страница компонента
<div id="main-container" style="text-align:center">
<div class="container">
<h2 *ngIf="user">Hello {{user.userName}}!</h2>
<form (ngSubmit)="sendMessage()" #chatForm="ngForm">
<div>
<label for="message">Message</label>
<input type="text" id="message" name="message" [(ngModel)]="message" required>
</div>
<button type="submit" id="sendmessage" [disabled]="!chatForm.valid">
Send
</button>
</form>
</div>
<div class="container" *ngIf="messages.length > 0">
<div *ngFor="let message of messages">
<span>{{message}}</span>
</div>
</div>
</div>
<div class="form-group">
<input type="button" value="getmessages" (click)="getmessages()" class="btn btn-success" />
</div>
уже и базу настроил, и все подключил, а сделать так, чтобы переписка шла только в своем чате не получается:(
Установил условие, что если отправитель не является тем - кому я сам пишу сообщение или просто к кому вошел в чат, то отправленное мне сообщение не появляется на экране - this.userForMessage.userName == nick
, но чтобы отправитель видел, что сообщение отправилось, и оно действительно отправилось пользователю и записалось в базу данных, я добавляю - || this.user.userName==nick
В целом это выглядит так:
this._hubConnection.on('Receive', (dateTime: string, nick: string, receivedMessage: string) => {
if (this.userForMessage.userName == nick || this.user.userName==nick) {
const text = `${dateTime}: ${nick}: ${receivedMessage}`;
this.messages.push(text);
}
});
В итоге все работает так, как и хотел, захожу первым пользователем в чат ко второму, вторым к третьему. Первым пишу сообщение, у второго тишина, захожу вторым пользователем к первому, вижу отправленное ранее сообщение (это с условием, если у вас как и у меня настроено сохранение сообщений в базе данных итп) вот и все!
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Есть DataGrid, в ней несколько колонок, одна из них с ComboboxСписок для Combobox подгружаю из внешнего файла
Собственно говоря как добавить поддержку форматаfb2 я пробовал добавить вот такой код в functions