ASP.NET Core、Angular 2、ダミー用SignalR

みなさんこんにちは! ASP.Net CoreとSignalRを使用したAngular 2を使用した経験を共有したいと思います。



1Cプログラマーとして、多くの場合、1Cでは解決が困難または不可能な問題を解決する必要があります。 .Netを知ることは本当に役立ちます。 しかし、サイトのクライアント側に関しては、使用しないとすぐに忘れられる多くの微妙な点(JavaScript、CSS、JQueryなど)があります。



Angular 2は、クライアント側の作成を大幅に簡素化できます。 そのため、TypeScriptはC#にはるかに近く(そして最も重要なこととして、ロシア語を使用できるようになります)、RazorとXamlを知っているテンプレートを簡単に見つけ出すことができます。



主なことは、WPFと同様にデータを操作することです。 たくさんのコントロールがあります。



勉強する資料を探すのにかなりの時間を費やしたので、私と同じ貧しい仲間、またはAngular 2、ASP.Net Coreの勉強を始めたばかりの仲間と共有したいと思います。



猫のトレーニングのために、私の1C Messengerプロジェクトが選ばれ、メッセージ、ファイルを送信し、1Cユーザー、Webページ、Skypeのモバイルアプリケーション、WhatsApp間でデータを交換しましたここのソース



出るまで。 Net Core 1.2およびNetStandard 2、.Net CoreでのSignalRのクライアントサポートはありません



それでは始めましょう。 動作するには、次のものが必要です。



1. Visual Studio用ASP.NET Core + Angular 2テンプレート

2. ASP.NET Coreガイド

3. Angular 2ガイド

4. TypeScriptガイド

5. PrimeNGのコンポーネント

6. ブートストラップのコンポーネント



Visual Studio用ASP.NET Core + Angular 2テンプレートは、多数のjsonファイルを作成し、webpackの使用を要求することにより、ASP.Net CoreとAngular 2を使用するようにアプリケーションを設定する素晴らしいテンプレートです。 たとえば、 Visual Studio 2015でのAngular2の起動に関する記事を読むことができます。



そして最も重要なことは、デバッグ中にtsおよびhtmlファイルを変更し、ページが更新されたときに変更を確認できることです。 Microsoft.AspNetCore.SpaServices.dllのクラスがこれを担当します。

WebpackDevMiddlewareOptionsおよびSpaRouteExtensions。 はい、はい! ブラウザでデバッグできます。 この場合、Tsファイルはフォルダー(ドメインなし)にあります



さらに、テンプレートにはたくさんの例があります! ただし、それらはすべてASCIIで保存されます。 キリル文字を使用する場合、tsとhtmlをUTF-8で再保存するのは面倒です。



PrimeNGのコンポーネントは、クライアントコードの作成を大幅に簡素化できます。 さらに、独自のコンポーネントの作成を検討し、既存のコンポーネントを変更できます。



SignalRハブを作成することから始めましょう。 型付きハブを使用すると便利です。



public interface IHelloHub { //         //  Camel  //        Task sendEcho(string str, string ); //   //  ,  Xamarin     4  Task addMessage(string Name, string str, string ConnectionId); }
      
      





このインターフェイスを実装するときは、sendEchoメソッドだけでなく制御します。 しかし、Clients.Others.addMessageおよびClients.Client(To).addMessageも。



  public class HelloHub : Hub<IHelloHub> { //    ,       //   ,      ID  public async Task sendEcho(string str, string ) { var user = new User(); if (!(user)) return; if (string.IsNullOrWhiteSpace()) await Clients.Others.addMessage(user.Name, str, user.ConnectionId); else await Clients.Client().addMessage(user.Name, str, user.ConnectionId); } }
      
      





さらに、このインターフェイスは.Netアプリケーションでの使用に便利であり、TypeScriptサービス記述用のコードジェネレーターを作成できます。



それでは、クライアントの作成に移りましょう。 まず、共通のサービスを作成し、 すべてのコンポーネントに対して1つのサービスを作成します。



これにより、ページの存続期間中、サービスを存続させることができ、コンポーネントはページ内をナビゲートした後、データを読み取り、データを読み取ります。



SignalRサービスコード
 /// <reference path="../models/ForHelloHub.ts"/> import { IHelloHub, DataInfo, ChatMessage, User} from "../models/ForHelloHub"; import { EventEmitter } from '@angular/core'; import { SelectItem } from 'primeng/primeng'; declare var $: any; export class HelloHub implements IHelloHub { //   public allMessages: ChatMessage[]; //     public connectionExists: Boolean; //    public isRegistered: Boolean; // $.connection.helloHub.server private server: any; // $.connection.helloHub.client private client: any; // $.connection.helloHub private chat: any; // ID  private userId: string; //   public Users: SelectItem[]; //      public onChangeUser: EventEmitter<void> = new EventEmitter<void>(); //     public onAddMessage: EventEmitter<void> = new EventEmitter<void>(); //      public onConnected: EventEmitter<void> = new EventEmitter<void>(); //     . public onRegistered: EventEmitter<void> = new EventEmitter<void>(); constructor() { this.userId = ""; //      "".    //     ,   this.Users = [{ label: "", value: ""}]; this.connectionExists = false; this.isRegistered = false; this.chat = $.connection.helloHub; this.server = this.chat.server; this.client = this.chat.client; //    this.registerOnServerEvents(); this.allMessages = new Array<ChatMessage>(); //    this.startConnection(); } //    .     private sortUsers() { this.Users.sort((a, b: SelectItem) => { if (a.label == "") return -1; return a.label.toLocaleUpperCase().localeCompare(b.label.toLocaleUpperCase()); }); } //      private registerOnServerEvents(): void { let self = this; //     //Task addMessage(string Name, string str, string ConnectionId); this.client.addMessage = (name: string, message: string, ConnectionId: string) => { //    - console.log('addMessage ' + message); self.addMessage(name, message,ConnectionId); }; //     //Task onConnected(string id, string userName, List < User > users); this.client.onConnected = function (id: string, userName: string, allUsers: User[]) { self.isRegistered = true; self.userId = id; //    for (let user of allUsers) { self.addUser(user.ConnectionId, user.Name); } self.sortUsers(); //      self.onRegistered.emit(); }; //Task onNewUserConnected(string id, string userName); //    this.client.onNewUserConnected = (id: string, name: string) => { self.addUser(id, name); }; //Task onUserDisconnected(string id, string Name); //   this.client.onUserDisconnected = (id: string, userName: string) => { let idx = self.Users.findIndex((cur: SelectItem) => { return cur.value == id; }); if (idx != -1) { return self.Users.splice(idx, 1); }; } } //    id //        findUser(userName:string,id: string): SelectItem { let idx = this.Users.findIndex((cur: SelectItem) => { return cur.value == id; }); if (idx != -1) { return this.Users[idx]; } return { label: userName, value:id } } //     addMessage(name: string, message: string, ConnectionId: string): void { this.allMessages.splice(0, 0, new ChatMessage(message, new Date, this.findUser(name, ConnectionId))); this.onAddMessage.emit(); } //       addUser(id: string, name: string): void { if (this.userId === "") return; if (this.userId !== id) { let usr = { label: name, value: id }; this.Users.push(usr); this.sortUsers(); this.onChangeUser.emit(); } } //    private startConnection(): void { let self = this; $.connection.hub.start().done((data: any) => { console.log('startConnection ' + data); self.connectionExists = true; self.onConnected.emit(); console.log('Send onConnected'); }).fail((error) => { console.log('Could not connect ' + error); }); } //=======     //       sendEcho(str: string, : string) { this.server.sendEcho(str, ); } //     sendByName(message: string, : string) { this.server.sendByName(message, ); } //      connect(userName: string) { this.server.connect(userName); } }
      
      







コンポーネントの作成に移りましょう。



受信したメッセージを表示し、メッセージを送信するためのコンポーネント
 import { Component, NgZone, ViewChild, AfterViewInit } from '@angular/core'; import { HelloHub } from '../services/HelloHubServise'; import { ChatMessage } from '../models/ForHelloHub'; import { SelectItem} from 'primeng/primeng'; import { Dropdown2 } from '../Dropdown/Dropdown'; @Component({ selector: 'p-HelloHubComponent', template: require('./SignalRHelloHub.html') }) export class HelloHubComponent { @ViewChild(Dropdown2) public dropdown: Dropdown2; public allMessages: ChatMessage[]; public Users: SelectItem[]; public selectedUser: string; public Message: string; public selectUsername: boolean=false; constructor(private _signalRService: HelloHub) { //      this.subscribeToEvents(); //         this.allMessages = this._signalRService.allMessages; //     this.Users = _signalRService.Users; } //        public sendMessage() { if (this.dropdown.value == "") //   ""   ,   { this._signalRService.sendEcho(this.Message, ""); } else { //  1        if (!this.selectUsername) //     " "     this._signalRService.sendEcho(this.Message, this.dropdown.value); else //        this._signalRService.sendByName(this.Message, this.dropdown.selectedOption.label); } this.Message = ""; } private subscribeToEvents(): void { let self = this; //      this._signalRService.onAddMessage.subscribe(() => { self.allMessages = this._signalRService.allMessages; }); //     this._signalRService.onChangeUser.subscribe(() => { this.Users = self._signalRService.Users; } ); } }
      
      









コンポーネントは、単にサービスからイベントデータを読み取り、更新し、サービスのメソッドを介してメッセージを送信します。 さて、コンポーネントのHTMLコードを表示しましょう。



HTMLテンプレート


  <div class="container" id="MainMessage"> <form role="form" (ngSubmit)="sendMessage()"> <div class="form-group"> <textarea type="text" [(ngModel)]="Message" name="Message" class="form-control" placeholder=""></textarea> </div> <div class="form-group"> <div class="btn-group open"> <button type="submit" class="btn btn-info"></button> </div> <div class="btn-group" id="users"> <p-dropdown2 [options]="Users" [(ngModel)]="selectedUser" name="dropdownUsers"></p-dropdown2> </div> <div class="btn-group" id="SendByName"> <div class="checkbox"> <label> <input type="checkbox" name="CheckBoxSendByName" [(ngModel)]="selectUsername" [disabled]="dropdown.value==''">   </label> </div> </div> </div> </form> </div> <div class="row"> <div class="col-xs-12 col-md-8" id="GetingMessage"> <template ngFor let-item [ngForOf]="allMessages"> <div class='panel panel-primary'> <div class='panel-heading'> {{item.From.label}}  {{item.Sent.toLocaleString()}} </div> <div class='panel-body'> {{item.Message}} </div> </div> </template> </div> <div class="col-xs-6 col-md-4"> </div> </div>
      
      





メッセージを送信するためのフォームがあります。これには、Messageプロパティバインディングを含むtextarea、接続ユーザーに関するデータを含むドロップダウン、名前でメッセージを送信するためのselectUsernameバインディングを含むチェックボックスが含まれます。



そして、受信メッセージallMessagesを持つブロックがあります。 Html自体はコンパクトで、すべてのコードは非常に優れたTypeScriptでした。



クロージャ内でのselfの使用に注意を払います。 これはJSによるものです。 JS自体のTSコンパイラは以下を生成します。



 var _this = this;
      
      





そして置き換えます



 var transport = this.chat.transport;
      
      









 var transport = _this.chat.transport;
      
      





しかし、デバッグには中間変数を使用すると便利です



  let self = this;
      
      





ソースはここにあります



さて、ヒープと記事とテンプレートJavaScript、Angular 2、Ionic 2を使用して、見栄えの良い、高速のモバイルアプリを作成します。



Angular 2はすべての面に搭載されています



All Articles