Моя задача - организовать соединение через веб-сокет между angular 7 и Web API в C #. Я пытался использовать библиотеку SignalR. Требуется, чтобы сервер отправлял push-уведомления клиенту о любых изменениях данных на стороне сервера. Клиент должен отображать эти данные в режиме реального времени. Я попытался выполнить некоторые из описанных выше реализаций, но возникли трудности: клиенту удается подключиться к серверу, но сервер через несколько секунд разрывает соединение.
Я пытался использовать класс Hub для получения сообщений с сервера. Мне удалось отправить сообщение клиенту с сервера, если я добавил метод для отправки сообщения переопределенному методу-концентратору - OnConnected (). Сообщение пришло один раз, после чего пришли пустые сообщения с сервера. Помогите пожалуйста, может я где-то ошибся?
Класс запуска:
public class Startup
{
public void Configuration(IAppBuilder app)
{
GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => new UnityHubActivator(UnityConfiguration.GetConfiguredContainer()));
// This server will be accessed by clients from other domains, so
// we open up CORS. This needs to be before the call to
// .MapSignalR()!
//
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
// Add SignalR to the OWIN pipeline
//
var hubConfiguration = new HubConfiguration();
app.MapSignalR("/signalr", hubConfiguration);
// Build up the WebAPI middleware
//
var httpConfig = new HttpConfiguration();
httpConfig.MapHttpAttributeRoutes();
app.UseWebApi(httpConfig);
}
}
Класс UnityConfigurator:
public class UnityConfiguration
{
#region Unity Container
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;
}
#endregion
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<ChatHub, ChatHub>(new ContainerControlledLifetimeManager());
container.RegisterType<IHubActivator, UnityHubActivator>(new ContainerControlledLifetimeManager());
}
}
Класс HubActivator:
public class UnityHubActivator : IHubActivator
{
private readonly IUnityContainer _container;
public UnityHubActivator(IUnityContainer container)
{
_container = container;
}
public IHub Create(HubDescriptor descriptor)
{
if (descriptor == null)
{
throw new ArgumentNullException("descriptor");
}
if (descriptor.HubType == null)
{
return null;
}
object hub = _container.Resolve(descriptor.HubType) ?? Activator.CreateInstance(descriptor.HubType);
return hub as IHub;
}
}
Класс концентратора:
[HubName("chathub")]
public class ChatHub : Hub
{
public void OnMessageReceived(string name, string message)
{
Clients.All.onMessageReceived(name, message);
}
public override Task OnConnected()
{
OnMessageReceived("onMessageRecerved", "Test message from server");
Debug.WriteLine("Hub connected ...");
return base.OnConnected();
}
}
Класс контроллера:
[RoutePrefix("api")]
public class ClockController : ApiController
{
private readonly IHubContext<ChatHub> _hub;
public ClockController(IHubContext<ChatHub> hub)
{
_hub = hub;
}
[Route("time")]
public IHttpActionResult Get()
{
_hub.Clients.All.OnMessageReceived("onMessageRecerved", DateTime.Now.ToString("h: mm: ss tt"));
return Ok(new { Message = "Request complete ..." });
}
}
И код клиента:
import { Injectable } from '@angular/core';
declare var $: any;
@Injectable()
export class SignalRService {
private connection: any;
private proxy: any;
constructor() { }
public initializeSignalRConnection(): void {
let signalRServerEndPoint = 'http://localhost:56143';
this.connection = $.hubConnection(signalRServerEndPoint);
this.proxy = this.connection.createHubProxy('chathub');
this.proxy.on('onMessageRecerved', (serverMessage) => this.onMessageReceived(serverMessage));
this.connection.start().done((data: any) => {
console.log('Connected to Notification Hub');
this.broadcastMessage();
}).catch((error: any) => {
console.log('Notification Hub error -> ' + error);
});
}
private broadcastMessage(): void {
this.proxy.invoke('ReceiveMessage', 'text message')
.catch((error: any) => {
console.log('broadcastMessage error -> ' + error);
});
}
private onMessageReceived(serverMessage: string) {
console.log('New message received from Server: ' + serverMessage);
}
}
ChatComponent.ts
import { Component, OnInit } from '@angular/core';
import { SignalRService } from '../../services/signal-r.service';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-clock',
templateUrl: './clock.component.html',
styleUrls: ['./clock.component.css']
})
export class ChatComponent implements OnInit {
constructor(public signalRService: SignalRService, private http: HttpClient) { }
ngOnInit() {
this.signalRService.initializeSignalRConnection();
}
private startHttpRequest = () => {
this.http.get('http://localhost:56143/api/time')
.subscribe(res => {
console.log(res);
})
}
}
Сервер разрывает соединение через веб-сокет через несколько секунд. Клиент получил только одно сообщение от сервера. После получения каждые 10 секунд приходят пустые объекты к клиенту.