Asp.net 类似信号器的功能不起作用
我已经创建了一个类似的功能,这样用户就可以喜欢我的应用程序中的帖子。我读过关于SignalR的文章,并尝试使用它,以便在用户喜欢/不喜欢帖子时,可以实时自动更新喜欢的次数。但是,它不起作用,但我也没有收到任何错误。按下like按钮后,我的控制台中的唯一消息是:Asp.net 类似信号器的功能不起作用,asp.net,angular,signalr,signalr-hub,Asp.net,Angular,Signalr,Signalr Hub,我已经创建了一个类似的功能,这样用户就可以喜欢我的应用程序中的帖子。我读过关于SignalR的文章,并尝试使用它,以便在用户喜欢/不喜欢帖子时,可以实时自动更新喜欢的次数。但是,它不起作用,但我也没有收到任何错误。按下like按钮后,我的控制台中的唯一消息是: Information: WebSocket connected to wss://localhost:44351/hubs/like?access_token=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.e
Information: WebSocket connected to wss://localhost:44351/hubs/like?access_token=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiIxIiwidW5pcXVlX25hbWUiOiJnZW9yZ2lhIiwicm9sZSI6WyJNZW1iZXIiLCJBZG1pbiJdLCJuYmYiOjE2MTk0NjQ3NzAsImV4cCI6MTYyMDA2OTU3MCwiaWF0IjoxNjE5NDY0NzcwfQ.1Bwf_Y2QJP_VjRUXaBeqz5sueV6oTIpVlOLU4kOEmLf2Y_hfxJbc5_f4yksY9R45YGz0qPWw-rc10I7pobFJYQ
export class PostCardComponent implements OnInit {
@Input() post: Post;
likesSubscription: Subscription;
constructor(private postService:PostsService,public accountService:AccountService)
{ this.Login$ = this.accountService.Logged;}
ngOnInit(): void {
this.likesSubscription = this.postService.likeMessageReceive.subscribe(result =>{
if (result.postId === this.post.id) {
this.post.likes.length = result.numOfLikes;
}
})
}
liked(post: Post) {
const user: User = JSON.parse(localStorage.getItem('user'));
this.postService.setLike(user.id, post.id);
}
}
这是我的.net代码:
public class LikeHub : Hub
{
private readonly IPostRepository _postRepository;
private readonly DataContext _context;
private readonly IUserRepository _userRepository;
public LikeHub(IPostRepository postRepository, DataContext context, IUserRepository userRepository)
{
_postRepository = postRepository;
_context = context;
_userRepository = userRepository;
}
public async Task SetLike(int userId, int postId)
{
Like l = new Like();
Like temp = _context.Likes.Where(x => x.PostId == postId && x.UserId == userId).FirstOrDefault();
if(temp != null)
{
_context.Likes.Remove(temp);
} else
{
_context.Likes.Add(l);
l.UserId = userId;
l.PostId = postId;
}
await _context.SaveChangesAsync();
int numOfLikes = _context.Likes.Where(x => x.PostId == postId).Count();
await Clients.All.SendAsync("ReceiveMessage", numOfLikes, postId, userId);
}
}
这是我在PostsService中的角度代码:
export class PostsService {
hubUrl = environment.hubUrl;
private hubConnection: HubConnection;
likeMessageReceive: EventEmitter<{ numOfLikes: number, postId: number, userId: number }> = new EventEmitter<{ numOfLikes:number, postId: number, userId: number }>();
constructor(private http: HttpClient) {}
connectHubs(user: User) {
this.hubConnection = new HubConnectionBuilder()
.withUrl(this.hubUrl + 'like', { accessTokenFactory: () => user.token,
skipNegotiation: true, transport: signalR.HttpTransportType.WebSockets })
.build();
return this.hubConnection.start()
.then(() => {
this.hubConnection.on('ReceiveMessage', (numOfLikes, postId, userId) => {
this.likeMessageReceive.emit({ numOfLikes, postId, userId });
});
})
.catch(error => console.log(error));
}
setLike(userId: number, postId: number) {
this.hubConnection.invoke('SetLike', userId, postId);
}
closeHubConnections() {
this.hubConnection.stop();
}
}
这是PostListComponent,其中所有帖子都是:
export class PostListComponent implements OnInit {
posts: Post[];
post: Post;
likesSubscription: Subscription;
localUser: User;
constructor(private postService: PostsService) {}
ngOnInit(): void {
this.postService.connectHubs(this.localUser);
}
}
我不知道
this.hubConnection.on()
中的代码是否正确,或者给定的参数是否正确。我还将LikeHub添加到Startup.cs类的端点中。我强烈建议从仔细重写这个示例开始,这确实有助于更好地理解概念
因此,这段代码中有几个问题。PostsService的createLike方法应该只负责通过现有连接进行后期调用。在此之前,负责连接启动的所有其他代码都应该已经执行。
因此,如果您不熟悉反应式编程和rxjs,我建议您在PostsService中添加一些方法,如ConnectHubs():承诺在实际调用某些hub方法之前准备好hub连接
connectHubs() {
this.hubConnection = new HubConnectionBuilder()
.withUrl(this.hubUrl + 'like', { accessTokenFactory: () => user.token,
skipNegotiation: true, transport: signalR.HttpTransportType.WebSockets })
.build();
return this.hubConnection.start()
.then(() => {
this.hubConnection.on('ReceiveMessage', (numOfLikes, postId, userId) => {
// some logic to handle invocation
});
})
.catch(error => console.log(error));
}
setLike(userId: number, postId: number) {
this.hubConnection.invoke('SetLike', userId, postId);
}
closeHubConnections() {
this.hubConnection.stop();
}
然后在包含多个post的组件中,除了从api请求所有post之外,您还需要调用这个connectHubs方法并等待这个承诺显示所有post,以避免在可能之前设置like。在这种情况下,最好在Ngondestory中停止连接,以避免从一个客户端到同一个集线器的不必要的多个活动连接。或者,您可以在非常基础的组件中调用此init方法,如应用程序组件,在这种情况下,您不需要在Ngondestory中停止连接,但需要确保您的用户在建立连接之前已登录。也许您可以找到一些组件,在这些组件中,它很少会被销毁,但它总是在登录后打开
如果您了解rxjs,可以添加一些行为主体字段,如
private isConnectedSubject = new BehaviorSubject(false);
isConnected$ = isConnectedSubject.asObservable();
然后,不必在连接开始时返回承诺,只需添加类似isConnectedSubject.next(true)的内容即可;
在断开连接的方法中,可以添加isConnectedSubject.next(false);
在您的组件中,当集线器未以这种方式连接时,您可以禁用like按钮:
<button [disabled]="!(postService.isConnected$ | async)" ...>
对于rxjs,这将是非常相似的,但您将使用Subject而不是emitter,不要忘记取消订阅以避免意外行为和泄漏。您可以在on处理程序中添加console.log(numOfLikes)并查看您收到了什么吗?你说它不起作用是什么意思?数据库更新了吗?还有,为什么要用喜欢的用户id更新用户id?数据库不会更新。userId是喜欢帖子的用户的id,postId是喜欢帖子的id。如果写入console.log(numOfLikes),则不会显示任何数据,断点甚至不会到达该点。这可能是因为我使用了then()?哦,真的,我甚至没有注意到:D尝试将其移动。在向上侦听器时,在创建HubConnectionBuilder().*.build()后,将正确发送传递给createLike()方法的用户和post参数。我已经更新了代码,并将connectionHub.on()与connectionHub.start()分开。现在断点到达connectionHub.on(),但它仍然没有到达我在生成后移动的conole.log(numOfLikes)。on,但仍然是相同的结果。我是否需要在后端使用Clients.Caller.SendAsync()呢?非常感谢!!我会仔细阅读这篇文章,在这些例子之后,我会尝试更新我的代码,以使其符合我的需要。好的,我已经尝试实施了你的建议,并用我收到的信息更新了问题中的Angular代码。由于我的帖子不再加载,所以出现了明显的错误:
error-TypeError:OnInit-from-PostListComponent中无法读取未定义的
属性“subscribe”。如果用户没有登录,like按钮甚至不会出现,所以我不需要禁用它。我认为PostList的OnInit中的代码可能不太正确,但是其他的看起来还可以吗?@Alessia好的,首先,您没有实例化事件发射器,可能我忘记添加此代码,您需要先创建它才能像这样使用它:likeMessageReceive=new EventEmitter()@Alessia和您仍然在创建中心连接,而不是进行方法调用。您需要在soe ngOnInit中添加connectHubs(),例如list,然后只需在您喜欢的方法中进行调用,就会更新答案,您放置的代码应该在subscribe中
likeMessageReceive = new EventEmitter<{ numOfLikes, postId, userId }>();
connectHubs() {
....
this.hubConnection.on('ReceiveMessage', (numOfLikes, postId, userId) => {
likeMessageReceive.emit({ numOfLikes, postId, userId })
console.log(numOfLikes);
})
....
likesSubscription: Subscription;
ngOnInit() {
this.likesSubscription = this.postsService.likeMessageReceive.subscribe(result =>{
if (result.postId === this.post.id) {
this.post.likes.length = numOfLikes;
}
})
}
liked(post: Post) {
const user: User = JSON.parse(localStorage.getItem('user'));
this.postService.setLike(user.id, post.id);
}
ngOnDestroy() {
if (this.likesSubscription) {
this.likesSubscription.unsubscribe();
}
}