Angularから信号接続を行う方法がわかりません。
https://docs.Microsoft.com/en-us/aspnet/signalr/overview/getting-started/tutorial-getting-started-with-signalr-and-mvc にある次のチュートリアルを使用する
Vs2017の既存の.Net 4.6ソリューションに新しいSignalR
2.4.0プロジェクトを追加しました。
_Angular 7
_を介してSignalR
パッケージを追加した_npm install @aspnet/signalr
_アプリケーションもあります
現在、クライアントとサーバー間の単純な接続を接続しようとしていますが、初期接続を確立する方法がわかりません。
フロントエンドが例外をスローし続けます。
_ core.js:15714 ERROR Error: Uncaught (in promise): Error: Cannot send data if the connection is not in the 'Connected' State.
_
エラー:接続が「接続済み」状態でない場合、データを送信できません。
フロントエンド検索コンポーネントに、テスト用のフィールドをいくつか追加しました。
_<mat-form-field>
<input matInput placeholder="message" [(ngModel)]="message">
</mat-form-field>
<button mat-button type="button" (click)="sendMessageToServer()"><span>Send</span></button>
<p *ngFor="let m of messages">{{m}}</p>
_
そして私のtsファイルで:
_// import other components/services here..
import { HubConnection, HubConnectionBuilder} from '@aspnet/signalr';
@Component({
selector: 'app-my-search',
templateUrl: './my-search.component.html',
styleUrls: ['./my-search.component.scss']
})
export class MySearchComponent implements OnInit {
public hubConnection: HubConnection;
public messages: string[] = [];
public message: string;
constructor() { }
ngOnInit() {
// SIGNALR MESSAGE HUB
let builder = new HubConnectionBuilder();
this.hubConnection = builder.withUrl('/SynBroadcastHub/BroadcastMessage').build(); // see startup.cs
this.hubConnection.on('notifyUser', (message) => {
this.messages.Push(message);
console.log(message);
});
this.hubConnection.start();
}
// signalr, send msg from client
sendMessageToServer() {
this.hubConnection.invoke('MessageToServer', this.message);
this.message = '';
}
}
_
c#側に、SignalR Hub Class (v2)
ファイルBroadcastHub.csを追加しました
_using Microsoft.AspNet.SignalR;
namespace SynBroadcastHub
{
public class BroadcastHub : Hub
{
/// Message to client
public void BroadcastMessage(string data)
{
Clients.Caller.notifyUser(data);
}
/// Message from client application; broadcast to all clients if requested.
public void MessageToServer(string data, bool notifyAllClients = false)
{
if (notifyAllClients)
{
Clients.All.NotifyAllClients(data);
}
}
}
}
_
また、_Startup.cs
_ファイル:
_using Microsoft.Owin;
using Microsoft.AspNet.SignalR;
using Owin;
[Assembly: OwinStartup(typeof(SynBroadcastHub.Startup))]
namespace SynBroadcastHub
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
HubConfiguration cfg = new HubConfiguration();
app.MapSignalR<PersistentConnection>("BroadcastHub/BroadcastMessage");
app.MapSignalR(cfg);
app.MapSignalR();
//app.MapSignalR<NotifyHub>("notify"); ???
}
public override Task OnDisconnected(bool stopCalled)
{
return Clients.All.leave(Context.ConnectionId, System.DateTime.Now.ToString());
}
public override Task OnConnected()
{
return Clients.All.joined(Context.ConnectionId, DateTime.Now.ToString());
}
public override Task OnReconnected()
{
return Clients.All.rejoined(Context.ConnectionId, DateTime.Now.ToString());
}
}
}
_
私はこれと同じことを理解するために2日間費やしました。私はついにそれを動作させました、そしてこれらは私がしなければならなかったいくつかのことです:
1)_@aspnet/signalr
_パッケージの使用は.Netフレームワークでは正しくないことに気付きましたが、それは正しいことです。 signalr
パッケージ(_npm install signalr
_)が必要です。
2)これはプロセス全体の中で最も重要な部分です。 SignalR
はjQuery
に依存しています。シグナルスクリプトを含むjQuerybeforeを含めるする _angular.json
_ファイルのscripts
セクションに、以下を含める必要があります。
_
"./node_modules/jquery/dist/jquery.js", "./node_modules/signalr/jquery.signalR.js"
_
その正確な順序で。プロジェクトの起動時に、最初にjQueryがロードされ、次にsignalRスクリプトがロードされます。
他の多くのスタックオーバーフローは、このエラーへの返信で質問に答えます。
_jQuery was not found. Please ensure jQuery is referenced before the SignalR client JavaScript file
_
jQueryを使用するコンポーネントに_import * as $ from "jquery"
_を書き込むように指示します。ただし、[〜#〜]ではありません[〜#〜]これを行うには正しい。その理由は、このangular記事 グローバルスクリプトについて によると、import
構文を使用するとmodule
ロードに含まれるためです。 _vendor.js
_コマンドの実行から作成された_ng build
_ファイルに入れます。これが問題である理由は、jQueryがまずangular.jsonから読み込まれ、次にsignalRが読み込まれるためです。 vendor.jsのモジュールはjQueryを再ロードし、signalRからjQueryにアタッチされたすべてのイベントをアタッチ解除します。
3)Signalerの.Net Coreバージョンを使用していることに気付いたため、angularコンポーネントで新しいHubConnectionをインスタンス化しようとすると、HubConnectionBuilder
にアクセスできなくなります。
代わりに、シグナルスクリプトが実行されると、コード内の_$
_に追加のイベントがアタッチされます。 注:tsファイルからビルド時またはコンパイル時にエラーが発生する場合は、npmから_@types/signalr
_および_@types/jquery
_が含まれていることを確認してください
新しいハブ接続を設定するには、$.hubConnection("your-url-here/signalr")
を使用します。これは、実行時にサーバーのハブに接続されます。 注:この結果をhubConnection
という変数としてmy angular componentに保存しました
Hubクラスがあるサーバーコード(.csファイル)で、クラス名の上に[HubName("YourHubName")]
を追加する必要があります。したがって、あなたの場合、あなたの.csファイルは上のようになります:
_[HubName("Broadcast")]
public class BroadcastHub : Hub
_
ほとんどの場合、これを.csファイルの先頭に含める必要があります:_using Microsoft.AspNet.SignalR.Hubs;
_
次に、Angularコンポーネントで、サーバーのハブに接続するようにプロキシを設定します。新しいhubConnectionをインスタンス化した直後の行には、次のように記述します。
this.hubConnection.createHubProxy("yourHubName");
。
あなたの場合、this.hubConnection.createHubProxy("broadcast");
プロキシを作成したら、リスナーをアタッチしてサーバーから発行されたイベントをリッスンするか、angularコンポーネントからサーバー関数を呼び出すことができます。
ここで example を実行して、呼び出しイベントを設定し、サーバーイベントをリッスンする方法を学びました。はい、それはangular 2ですが、Signalerからの機能はすべて、私のangular 7アプリで同じように機能します。
短い答え:サーバーからのイベントをproxy.on('eventname')
tolistenして、proxy.invoke('eventname')
tocallangularコンポーネントからのハブ上の関数。
最後に、csファイル内のいくつかのメモ。私のStartup.csで、シグナルをマッピングするために持っている唯一のものはapp.MapSignalR()
です。私はあなたがしたように設定する他のプロパティに関する多くの詳細には行きませんでした、しかしそれはいくつかの問題のもう一つの原因かもしれませんか?
私はこの主題を自分で調査していて、npmパッケージng2-signalを見つけました。たぶん自分を調べる何かですか?
HubEndpointが正しいことを確信していますか?ハブがangularルーティングの一部であるようです(作成方法から判断して)。フルパスを設定してみてください(例: https:// www。 myapp.com/SynBroadcastHub/BroadcastMessage )
signalRパッケージをインストールします
npm i @ aspnet/signalr --save
import { Component, OnInit } from '@angular/core';
import { HubConnection } from '@aspnet/signalr';
import * as signalR from '@aspnet/signalr';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
private hubConnection: HubConnection;
public ngOnInit() {
this.hubConnection = new signalR.HubConnectionBuilder()
.withUrl("http://localhost:50930/pushNotification").build();
this.hubConnection.start().then(() => {
console.log("connection started");
}).catch(err => console.log(err));
this.hubConnection.onclose(() => {
debugger;
setTimeout(() => {
debugger;
this.hubConnection.start().then(() => {
debugger;
console.log("connection started");
}).catch(err => console.log(err));
}, 5000);
});
this.hubConnection.on("clientMethodName", (data) => {
debugger;
console.log(data);
});
this.hubConnection.on("WelcomeMethodName", (data) => {
debugger;
console.log(data);
this.hubConnection.invoke("GetDataFromClient", "user id", data).catch(err => console.log(err));
});
}
public stopConnection() {
this.hubConnection.start().then(() => {
console.log("stopped");
}).catch(err => console.log(err));
}
}
netcoreapp2.2を使用したWeb API
インストールMicrosoft.AspNetCore.SignalR
Startup.cs
クライアントはポート4200で実行されています( " http:// localhost:42 ")。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace SignalRWebApp
{
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.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddCors(option =>
{
option.AddPolicy("CorsPolicy", builder =>
builder.WithOrigins("http://localhost:4200")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
services.AddSignalR();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors("CorsPolicy");
app.UseSignalR(routes =>
{
routes.MapHub<SignalHub>("/pushNotification");
});
app.UseHttpsRedirection();
app.UseMvc();
}
}
}
SignalHub.cs
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace SignalRWebApp
{
public class SignalHub : Hub
{
public void GetDataFromClient(string userId, string connectionId)
{
Clients.Client(connectionId).SendAsync("clientMethodName", $"Updated userid {userId}");
}
public override Task OnConnectedAsync()
{
var connectionId = Context.ConnectionId;
Clients.Client(connectionId).SendAsync("WelcomeMethodName", connectionId);
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception exception)
{
var connectionId = Context.ConnectionId;
return base.OnDisconnectedAsync(exception);
}
}
}
次の例のようにsignalRメッセージを送信します
[Route("api/[controller]")]
[ApiController]
[EnableCors("CorsPolicy")]
public class ValuesController : ControllerBase
{
private IHubContext<SignalHub> _hub;
public ValuesController(IHubContext<SignalHub> hub)
{
_hub = hub;
}
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
_hub.Clients.All.SendAsync("clientMethodName", "get all called");
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{connectionId}")]
public ActionResult<string> Get(string connectionId)
{
_hub.Clients.Client(connectionId).SendAsync("clientMethodName", "get called");
return "value";
}
}
}