【发布时间】:2022-10-17 20:01:55
【问题描述】:
我正在尝试为我的应用程序制作一种实时位置共享功能,但 SignalR 部分存在一些问题。
只是对我在这里尝试做的事情的简短描述:这个中心应该只发送实时分享他们位置的人。首先,我尝试为发件人建立连接,当按下开始按钮时,连接开始,但它一直处于“正在连接”状态,并且将发送其位置的新用户的消息不会注册了,我想知道我做错了什么。我按照教程进行聊天并尝试适应我的需求,但可能需要添加或编辑某些内容才能按我的意愿工作。
分享-live.component.ts
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { BehaviorSubject } from 'rxjs';
import { take } from 'rxjs/operators';
import { MapService } from 'src/app/services/location/map.service';
import { AccountService } from 'src/app/shared/services';
import { ShareLiveService } from '../services/share-live.service';
@Component({
selector: 'app-share-live',
templateUrl: './share-live.component.html',
styleUrls: ['./share-live.component.scss']
})
export class ShareLiveComponent implements OnDestroy{
userPosition: google.maps.LatLngLiteral = null;
username: string;
stopWatch = true;
connectedToHub = false;
isSharing = new BehaviorSubject<boolean>(false);
id: number;
options: google.maps.MapOptions = {
center: {lat: 45.9432, lng: 26.5},
zoom: 16
};
markerOptions: google.maps.MarkerOptions = {
clickable: true,
draggable: false,
};
markerSettings = [
{
visible:true,
shape:'Circle',
fill:'white',
width:3,
animationDuration:0,
border:{width:2,color:'#333'}
}
];
constructor(
readonly mapService: MapService,
private readonly shareLiveService: ShareLiveService,
private readonly accountService: AccountService
) {
this.accountService.currentUserSource
.pipe(take(1))
.subscribe(user => this.username = user.username);
this.positionMap();
}
ngOnDestroy(): void {
if(this.connectedToHub){
this.stopHubConnection();
}
}
start(): void {
this.stopWatch = false;
this.isSharing.next(!this.stopWatch);
this.connectDisconectHub();
this.id = navigator.geolocation.watchPosition((position) => {
console.log(position);
this.refreshOptions(position.coords);
this.refreshLocation(position.coords);
});
}
stop(): void {
this.stopWatch = true;
this.connectDisconectHub();
if(this.id){
navigator.geolocation.clearWatch(this.id);
this.id = null;
this.isSharing.next(!this.stopWatch);
}
}
private connectDisconectHub(): void {
if(!this.connectedToHub){
this.createHubConnection();
} else {
this.stopHubConnection();
}
}
private createHubConnection(): void {
this.shareLiveService.createHubConnection(this.username);
this.connectedToHub = true;
}
private stopHubConnection(): void {
this.shareLiveService.eraseSharer(this.username)
.catch(error=> console.log(error));
this.shareLiveService.stopHubConnection();
this.connectedToHub = false;
}
private positionMap(): void {
navigator.geolocation.getCurrentPosition((position) => {
this.refreshOptions(position.coords);
});
}
private refreshOptions(coordinates: GeolocationCoordinates): void {
this.options = {
...this.options,
center: {lat: coordinates.latitude, lng: coordinates.longitude}
};
}
private refreshLocation(coordinates: GeolocationCoordinates): void {
this.userPosition = {lat: coordinates.latitude, lng: coordinates.longitude};
}
}
分享-live.service.ts
import { Injectable } from '@angular/core';
import { HttpTransportType, HubConnection, HubConnectionBuilder } from '@microsoft/signalr';
import { BehaviorSubject, Observable } from 'rxjs';
import { LocationCoords } from 'src/app/shared/types';
import { environment } from 'src/environments/environment';
@Injectable({
providedIn: 'root'
})
export class ShareLiveService {
hubUrl = environment.hubUrl;
livesharerSource$: Observable<{username: string}[]>;
private hubConnection: HubConnection;
private livesharer = new BehaviorSubject<{username: string}[]>([]);
constructor() {
this.livesharerSource$ = this.livesharer.asObservable();
}
createHubConnection(username: string): void {
this.hubConnection = new HubConnectionBuilder()
.withUrl(this.hubUrl + 'locationsharers',{
skipNegotiation: true,
transport: HttpTransportType.WebSockets
})
.build();
this.hubConnection.start()
.then(() => this.sendNewSharer(username))
.catch(error => console.log(error));
}
stopHubConnection(): void {
if(this.hubConnection){
this.hubConnection.stop()
.then(() => console.log('Connection stopped!'))
.catch(error => console.log(error));
}
}
async sendNewSharer(username: string): Promise<any> {
return this.hubConnection.invoke('AddNewSharer', username)
.catch(error => console.log(error));
}
async eraseSharer(username: string): Promise<any> {
return this.hubConnection.invoke('RemoveSharer', username)
.catch(error => console.log(error));
}
}
环境.ts
export const environment = {
production: false,
url:'https://localhost:5001/api',
hubUrl: 'http://localhost:5001/hubs/',
mapbox: {
accessToken: 'token'
}
};
LiveLocationSharersHub.cs
using DataAccessAPI.DTOs;
using DataAccessAPI.Entities;
using DataAccessAPI.Interfaces;
using Microsoft.AspNetCore.SignalR;
namespace DataAccessAPI.SignalR
{
public class LiveLocationSharersHub : Hub
{
private readonly ILiveLocationSharersRepository _liveLocationSharersRepository;
private readonly ILiveLocationRepository _liveLocationRepository;
public LiveLocationSharersHub(ILiveLocationSharersRepository liveLocationSharersRepository, ILiveLocationRepository liveLocationRepository)
{
_liveLocationSharersRepository = liveLocationSharersRepository;
_liveLocationRepository = liveLocationRepository;
}
public override async Task OnConnectedAsync()
{
var httpContext = Context.GetHttpContext();
await Groups.AddToGroupAsync(Context.ConnectionId, "people-sharing");
var peopleSharing = _liveLocationSharersRepository.GetAll();
await Clients.Group("people-sharing").SendAsync("PeopleSharingLocation", peopleSharing);
}
public override async Task OnDisconnectedAsync(Exception exception)
{
await base.OnDisconnectedAsync(exception);
}
public async Task AddNewSharer(string username)
{
if (!await _liveLocationRepository.UserExistsAsync(username))
{
throw new HubException("This user doesn't exist! Something is wrong.");
}
var newSharer = new LiveLocationSharer
{
Username = username
};
_liveLocationSharersRepository.AddSharer(newSharer);
if (await _liveLocationRepository.SaveAllAsync())
{
await Clients.Group("people-sharing").SendAsync("NewSharer", username);
}
else
{
throw new HubException("Something went wrong.");
}
}
public async Task RemoveSharer(string username)
{
if (!await _liveLocationRepository.UserExistsAsync(username))
{
throw new HubException("This user doesn't exist! Something is wrong.");
}
var sharer = await _liveLocationSharersRepository.GetLiveLocationSharersAsync(username);
_liveLocationSharersRepository.Delete(sharer);
if (await _liveLocationRepository.SaveAllAsync())
{
await Clients.Group("people-sharing").SendAsync("UserDeleted", username);
}
else
{
throw new HubException("Something went wrong.");
}
}
}
}
配置方法
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebAPIv5 v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(policy => policy.AllowAnyHeader().AllowAnyMethod().WithOrigins("http://localhost:8100"));
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<LiveLocationHub>("hubs/livelocation");
endpoints.MapHub<LiveLocationSharersHub>("hubs/locationsharers");
});
}
【问题讨论】:
-
好的:所以您的 Angular 客户端尝试 - 但从未真正“连接” - 到您的 ASP.Net Core 后端。正确的?问:您是否能够对 ASP.Net Core 进行故障排除?您是否看到任何连接请求?问:您使用的是哪个版本的 ASP.Net Core?
-
@paulsm4 是的,它从未真正“连接”过。我尝试在 OnConnectedAsync() 方法中放置一个断点,但它似乎没有到达它并且我没有看到任何连接请求。我正在使用 ASP.Net Core 6
-
@paulsm4 显然问题是 url 在 http 之后缺少 ':',但它仍然不起作用,我收到以下错误:1. WebSocket 连接到 'ws://localhost:5001/hubs/locationsharers'失败:2.[2022-10-08T16:52:57.249Z] 错误:无法启动连接:错误:WebSocket 连接失败。在服务器上找不到连接,端点可能不是 SignalR 端点,服务器上不存在连接 ID,或者存在阻止 WebSocket 的代理。如果您有多个服务器,请检查是否启用了粘性会话。
-
我赞成你的问题,并冒昧地更改了标题。请看这里(然后发回你的发现):stackoverflow.com/questions/70216272 问:你在哪里/如何在你的 Angular 应用程序中配置了“端点”?
-
@paulsm4 我在问题中添加了环境文件和配置方法。如果您还需要什么,请随时询问
标签: angular typescript signalr signalr.client asp.net-core-signalr