Bagikan melalui


Panduan API ASP.NET SignalR Hubs - Server (SignalR 1.x)

oleh Patrick Fletcher, Tom Dykstra

Peringatan

Dokumentasi ini bukan untuk versi terbaru SignalR. Lihatlah ASP.NET Core SignalR.

Dokumen ini menyediakan pengantar pemrograman sisi server ASP.NET SignalR Hubs API untuk SignalR versi 1.1, dengan sampel kode yang menunjukkan opsi umum.

SIGNALR Hubs API memungkinkan Anda melakukan panggilan prosedur jarak jauh (RPC) dari server ke klien yang terhubung dan dari klien ke server. Dalam kode server, Anda menentukan metode yang dapat dipanggil oleh klien, dan Anda memanggil metode yang berjalan pada klien. Dalam kode klien, Anda menentukan metode yang dapat dipanggil dari server, dan Anda memanggil metode yang berjalan di server. SignalR menangani semua pipa klien-ke-server untuk Anda.

SignalR juga menawarkan API tingkat bawah yang disebut Koneksi Persisten. Untuk pengenalan SignalR, Hub, dan Koneksi Persisten, atau untuk tutorial yang menunjukkan cara membangun aplikasi SignalR lengkap, lihat SignalR - Memulai.

Gambaran Umum

Dokumen ini berisi bagian berikut:

Untuk dokumentasi tentang cara memprogram klien, lihat sumber daya berikut:

Tautan ke topik Referensi API adalah ke API versi .NET 4.5. Jika Anda menggunakan .NET 4, lihat topik API versi .NET 4.

Cara mendaftarkan rute SignalR dan mengonfigurasi opsi SignalR

Untuk menentukan rute yang akan digunakan klien untuk terhubung ke Hub Anda, panggil metode MapHubs saat aplikasi dimulai. MapHubs adalah metode ekstensi untuk System.Web.Routing.RouteCollection kelas . Contoh berikut menunjukkan cara menentukan rute SignalR Hubs dalam file Global.asax .

using System.Web.Routing;
public class Global : System.Web.HttpApplication
{
    protected void Application_Start(object sender, EventArgs e)
    {
        RouteTable.Routes.MapHubs();
    }
}

Jika Anda menambahkan fungsionalitas SignalR ke aplikasi MVC ASP.NET, pastikan rute SignalR ditambahkan sebelum rute lainnya. Untuk informasi selengkapnya, lihat Tutorial: Memulai SignalR dan MVC 4.

The /signalr URL

Secara default, URL rute yang akan digunakan klien untuk terhubung ke Hub Anda adalah "/signalr". (Jangan bingung dengan URL ini dengan URL "/signalr/hubs", yaitu untuk file JavaScript yang dihasilkan secara otomatis. Untuk informasi selengkapnya tentang proksi yang dihasilkan, lihat Panduan API SignalR Hubs - Klien JavaScript - Proksi yang dihasilkan dan apa fungsinya untuk Anda.)

Mungkin ada keadaan luar biasa yang membuat URL dasar ini tidak dapat digunakan untuk SignalR; misalnya, Anda memiliki folder di proyek bernama signalr dan Anda tidak ingin mengubah namanya. Dalam hal ini, Anda dapat mengubah URL dasar, seperti yang ditunjukkan dalam contoh berikut (ganti "/signalr" dalam kode sampel dengan URL yang Anda inginkan).

Kode server yang menentukan URL

RouteTable.Routes.MapHubs("/signalr", new HubConfiguration());

Kode klien JavaScript yang menentukan URL (dengan proksi yang dihasilkan)

$.connection.hub.url = "/signalr"
$.connection.hub.start().done(init);

Kode klien JavaScript yang menentukan URL (tanpa proksi yang dihasilkan)

var connection = $.hubConnection("/signalr", { useDefaultPath: false });

Kode klien .NET yang menentukan URL

var hubConnection = new HubConnection("http://contoso.com/signalr", useDefaultUrl: false);

Mengonfigurasi Opsi SignalR

Kelebihan beban MapHubs metode memungkinkan Anda menentukan URL kustom, pemecah masalah dependensi kustom, dan opsi berikut:

  • Aktifkan panggilan lintas domain dari klien browser.

    Biasanya jika browser memuat halaman dari http://contoso.com, koneksi SignalR berada di domain yang sama, di http://contoso.com/signalr. Jika halaman dari http://contoso.com membuat koneksi ke http://fabrikam.com/signalr, itu adalah koneksi lintas domain. Untuk alasan keamanan, koneksi lintas domain dinonaktifkan secara default. Untuk informasi selengkapnya, lihat ASP.NET Panduan API SignalR Hubs - Klien JavaScript - Cara membuat koneksi lintas domain.

  • Aktifkan pesan kesalahan terperinci.

    Ketika kesalahan terjadi, perilaku default SignalR adalah mengirim pesan pemberitahuan kepada klien tanpa detail tentang apa yang terjadi. Mengirim informasi kesalahan terperinci ke klien tidak disarankan dalam produksi, karena pengguna jahat mungkin dapat menggunakan informasi dalam serangan terhadap aplikasi Anda. Untuk pemecahan masalah, Anda dapat menggunakan opsi ini untuk mengaktifkan pelaporan kesalahan yang lebih informatif untuk sementara waktu.

  • Nonaktifkan file proksi JavaScript yang dihasilkan secara otomatis.

    Secara default, file JavaScript dengan proksi untuk kelas Hub Anda dihasilkan sebagai respons terhadap URL "/signalr/hubs". Jika Anda tidak ingin menggunakan proksi JavaScript, atau jika Anda ingin membuat file ini secara manual dan merujuk ke file fisik di klien Anda, Anda dapat menggunakan opsi ini untuk menonaktifkan pembuatan proksi. Untuk informasi selengkapnya, lihat Panduan API SignalR Hubs - Klien JavaScript - Cara membuat file fisik untuk proksi yang dihasilkan SignalR.

Contoh berikut menunjukkan cara menentukan URL koneksi SignalR dan opsi ini dalam panggilan ke MapHubs metode . Untuk menentukan URL kustom, ganti "/signalr" dalam contoh dengan URL yang ingin Anda gunakan.

var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableCrossDomain = true;
hubConfiguration.EnableDetailedErrors = true;
hubConfiguration.EnableJavaScriptProxies = false;
RouteTable.Routes.MapHubs("/signalr", hubConfiguration);

Cara membuat dan menggunakan kelas Hub

Untuk membuat Hub, buat kelas yang berasal dari Microsoft.Aspnet.Signalr.Hub. Contoh berikut menunjukkan kelas Hub sederhana untuk aplikasi obrolan.

public class ContosoChatHub : Hub
{
    public void NewContosoChatMessage(string name, string message)
    {
        Clients.All.addNewMessageToPage(name, message);
    }
}

Dalam contoh ini, klien yang terhubung dapat memanggil NewContosoChatMessage metode , dan ketika itu terjadi, data yang diterima disiarkan ke semua klien yang terhubung.

Masa pakai objek hub

Anda tidak membuat instans kelas Hub atau memanggil metodenya dari kode Anda sendiri di server; semua yang dilakukan untuk Anda oleh alur SignalR Hubs. SignalR membuat instans baru kelas Hub Anda setiap kali perlu menangani operasi Hub seperti saat klien terhubung, memutuskan sambungan, atau melakukan panggilan metode ke server.

Karena instans kelas Hub bersifat sementara, Anda tidak dapat menggunakannya untuk mempertahankan status dari satu panggilan metode ke panggilan berikutnya. Setiap kali server menerima panggilan metode dari klien, instans baru kelas Hub Anda memproses pesan. Untuk mempertahankan status melalui beberapa koneksi dan panggilan metode, gunakan beberapa metode lain seperti database, atau variabel statis pada kelas Hub, atau kelas berbeda yang tidak berasal dari Hub. Jika Anda mempertahankan data dalam memori, menggunakan metode seperti variabel statis pada kelas Hub, data akan hilang saat domain aplikasi didaur ulang.

Jika Anda ingin mengirim pesan ke klien dari kode Anda sendiri yang berjalan di luar kelas Hub, Anda tidak dapat melakukannya dengan membuat instans kelas Hub, tetapi Anda dapat melakukannya dengan mendapatkan referensi ke objek konteks SignalR untuk kelas Hub Anda. Untuk informasi selengkapnya, lihat Cara memanggil metode klien dan mengelola grup dari luar kelas Hub nanti dalam topik ini.

Camel-casing nama Hub di klien JavaScript

Secara default, klien JavaScript merujuk ke Hub dengan menggunakan versi camel-cased dari nama kelas. SignalR secara otomatis membuat perubahan ini sehingga kode JavaScript dapat sesuai dengan konvensi JavaScript. Contoh sebelumnya akan disebut sebagai contosoChatHub dalam kode JavaScript.

Server

public class ContosoChatHub : Hub

Klien JavaScript menggunakan proksi yang dihasilkan

var contosoChatHubProxy = $.connection.contosoChatHub;

Jika Anda ingin menentukan nama yang berbeda untuk digunakan klien, tambahkan HubName atribut . Saat Anda menggunakan HubName atribut , tidak ada perubahan nama pada kasus camel pada klien JavaScript.

Server

[HubName("PascalCaseContosoChatHub")]
public class ContosoChatHub : Hub

Klien JavaScript menggunakan proksi yang dihasilkan

var contosoChatHubProxy = $.connection.PascalCaseContosoChatHub;

Beberapa Hub

Anda dapat menentukan beberapa kelas Hub dalam aplikasi. Saat Anda melakukannya, koneksi dibagikan tetapi grup terpisah:

  • Semua klien akan menggunakan URL yang sama untuk membuat koneksi SignalR dengan layanan Anda ("/signalr" atau URL kustom Anda jika Anda menentukannya), dan koneksi tersebut digunakan untuk semua Hub yang ditentukan oleh layanan.

    Tidak ada perbedaan performa untuk beberapa Hub dibandingkan dengan menentukan semua fungsi hub dalam satu kelas.

  • Semua Hub mendapatkan informasi permintaan HTTP yang sama.

    Karena semua Hub berbagi koneksi yang sama, satu-satunya informasi permintaan HTTP yang didapat server adalah apa yang masuk dalam permintaan HTTP asli yang membuat koneksi SignalR. Jika Anda menggunakan permintaan koneksi untuk meneruskan informasi dari klien ke server dengan menentukan string kueri, Anda tidak dapat menyediakan string kueri yang berbeda ke Hub yang berbeda. Semua Hub akan menerima informasi yang sama.

  • File proksi JavaScript yang dihasilkan akan berisi proksi untuk semua Hub dalam satu file.

    Untuk informasi tentang proksi JavaScript, lihat Panduan API SignalR Hubs - Klien JavaScript - Proksi yang dihasilkan dan apa yang dilakukannya untuk Anda.

  • Grup ditentukan dalam Hub.

    Di SignalR, Anda dapat menentukan grup bernama untuk disiarkan ke subset klien yang terhubung. Grup dipertahankan secara terpisah untuk setiap Hub. Misalnya, grup bernama "Administrator" akan menyertakan satu set klien untuk kelas Anda ContosoChatHub , dan nama grup yang sama akan merujuk ke sekumpulan klien yang berbeda untuk kelas Anda StockTickerHub .

Cara menentukan metode di kelas Hub yang dapat dipanggil klien

Untuk mengekspos metode di Hub yang ingin Anda panggil dari klien, nyatakan metode publik, seperti yang ditunjukkan dalam contoh berikut.

public class ContosoChatHub : Hub
{
    public void NewContosoChatMessage(string name, string message)
    {
        Clients.All.addNewMessageToPage(name, message);
    }
}
public class StockTickerHub : Hub
{
    public IEnumerable<Stock> GetAllStocks()
    {
        return _stockTicker.GetAllStocks();
    }
}

Anda dapat menentukan jenis pengembalian dan parameter, termasuk jenis dan array kompleks, seperti yang Anda lakukan dalam metode C# apa pun. Data apa pun yang Anda terima dalam parameter atau kembali ke pemanggil dikomunikasikan antara klien dan server dengan menggunakan JSON, dan SignalR menangani pengikatan objek kompleks dan array objek secara otomatis.

Camel-casing nama metode di klien JavaScript

Secara default, klien JavaScript merujuk ke metode Hub dengan menggunakan versi camel-cased dari nama metode. SignalR secara otomatis membuat perubahan ini sehingga kode JavaScript dapat sesuai dengan konvensi JavaScript.

Server

public void NewContosoChatMessage(string userName, string message)

Klien JavaScript menggunakan proksi yang dihasilkan

contosoChatHubProxy.server.newContosoChatMessage($(userName, message);

Jika Anda ingin menentukan nama yang berbeda untuk digunakan klien, tambahkan HubMethodName atribut .

Server

[HubMethodName("PascalCaseNewContosoChatMessage")]
public void NewContosoChatMessage(string userName, string message)

Klien JavaScript menggunakan proksi yang dihasilkan

contosoChatHubProxy.server.PascalCaseNewContosoChatMessage(userName, message);

Kapan harus mengeksekusi secara asinkron

Jika metode akan berjalan lama atau harus melakukan pekerjaan yang akan melibatkan menunggu, seperti pencarian database atau panggilan layanan web, buat metode Hub asinkron dengan mengembalikan Tugas (sebagai ganti void pengembalian) atau objek Task<T> (sebagai ganti T jenis pengembalian). Ketika Anda mengembalikan Task objek dari metode , SignalR menunggu Task hingga selesai, dan kemudian mengirim hasil yang dibongkar kembali ke klien, sehingga tidak ada perbedaan dalam cara Anda membuat kode panggilan metode di klien.

Membuat metode Hub asinkron menghindari pemblokiran koneksi saat menggunakan transportasi WebSocket. Ketika metode Hub dijalankan secara sinkron dan transportasinya adalah WebSocket, pemanggilan metode berikutnya pada Hub dari klien yang sama diblokir sampai metode Hub selesai.

Contoh berikut menunjukkan metode yang sama yang dikodekan untuk berjalan secara sinkron atau asinkron, diikuti oleh kode klien JavaScript yang berfungsi untuk memanggil salah satu versi.

Sinkron

public IEnumerable<Stock> GetAllStocks()
{
    // Returns data from memory.
    return _stockTicker.GetAllStocks();
}

Asinkron - ASP.NET 4,5

public async Task<IEnumerable<Stock>> GetAllStocks()
{
    // Returns data from a web service.
    var uri = Util.getServiceUri("Stocks");
    using (HttpClient httpClient = new HttpClient())
    {
        var response = await httpClient.GetAsync(uri);
        return (await response.Content.ReadAsAsync<IEnumerable<Stock>>());
    }
}

Klien JavaScript menggunakan proksi yang dihasilkan

stockTickerHubProxy.server.getAllStocks().done(function (stocks) {
    $.each(stocks, function () {
        alert(this.Symbol + ' ' + this.Price);
    });
});

Untuk informasi selengkapnya tentang cara menggunakan metode asinkron di ASP.NET 4.5, lihat Menggunakan Metode Asinkron di ASP.NET MVC 4.

Menentukan Kelebihan Beban

Jika Anda ingin menentukan kelebihan beban untuk metode, jumlah parameter di setiap kelebihan beban harus berbeda. Jika Anda membedakan kelebihan beban hanya dengan menentukan jenis parameter yang berbeda, kelas Hub Anda akan dikompilasi tetapi layanan SignalR akan memberikan pengecualian pada waktu proses ketika klien mencoba memanggil salah satu kelebihan beban.

Cara memanggil metode klien dari kelas Hub

Untuk memanggil metode klien dari server, gunakan Clients properti dalam metode di kelas Hub Anda. Contoh berikut menunjukkan kode server yang memanggil addNewMessageToPage semua klien yang terhubung, dan kode klien yang menentukan metode dalam klien JavaScript.

Server

public class ContosoChatHub : Hub
{
    public void NewContosoChatMessage(string name, string message)
    {
        Clients.All.addNewMessageToPage(name, message);
    }
}

Klien JavaScript menggunakan proksi yang dihasilkan

contosoChatHubProxy.client.addNewMessageToPage = function (name, message) {
    // Add the message to the page. 
    $('#discussion').append('<li><strong>' + htmlEncode(name)
        + '</strong>: ' + htmlEncode(message) + '<li>');
};

Anda tidak bisa mendapatkan nilai pengembalian dari metode klien; sintaks seperti int x = Clients.All.add(1,1) tidak berfungsi.

Anda dapat menentukan jenis kompleks dan array untuk parameter. Contoh berikut meneruskan jenis kompleks ke klien dalam parameter metode.

Kode server yang memanggil metode klien menggunakan objek kompleks

public void SendMessage(string name, string message)
{
    Clients.All.addContosoChatMessageToPage(new ContosoChatMessage() { UserName = name, Message = message });
}

Kode server yang menentukan objek kompleks

public class ContosoChatMessage
{
    public string UserName { get; set; }
    public string Message { get; set; }
}

Klien JavaScript menggunakan proksi yang dihasilkan

var contosoChatHubProxy = $.connection.contosoChatHub;
contosoChatHubProxy.client.addMessageToPage = function (message) {
    console.log(message.UserName + ' ' + message.Message);
});

Memilih klien mana yang akan menerima RPC

Properti Klien mengembalikan objek HubConnectionContext yang menyediakan beberapa opsi untuk menentukan klien mana yang akan menerima RPC:

  • Semua klien yang terhubung.

    Clients.All.addContosoChatMessageToPage(name, message);
    
  • Hanya klien panggilan.

    Clients.Caller.addContosoChatMessageToPage(name, message);
    
  • Semua klien kecuali klien panggilan.

    Clients.Others.addContosoChatMessageToPage(name, message);
    
  • Klien tertentu yang diidentifikasi oleh ID koneksi.

    Clients.Client(Context.ConnectionId).addContosoChatMessageToPage(name, message);
    

    Contoh ini memanggil addContosoChatMessageToPage klien panggilan dan memiliki efek yang sama seperti menggunakan Clients.Caller.

  • Semua klien yang terhubung kecuali klien yang ditentukan, diidentifikasi oleh ID koneksi.

    Clients.AllExcept(connectionId1, connectionId2).addContosoChatMessageToPage(name, message);
    
  • Semua klien yang terhubung dalam grup tertentu.

    Clients.Group(groupName).addContosoChatMessageToPage(name, message);
    
  • Semua klien yang terhubung dalam grup tertentu kecuali klien yang ditentukan, yang diidentifikasi oleh ID koneksi.

    Clients.Group(groupName, connectionId1, connectionId2).addContosoChatMessageToPage(name, message);
    
  • Semua klien yang terhubung dalam grup tertentu kecuali klien panggilan.

    Clients.OthersInGroup(groupName).addContosoChatMessageToPage(name, message);
    

Tidak ada validasi waktu kompilasi untuk nama metode

Nama metode yang Anda tentukan ditafsirkan sebagai objek dinamis, yang berarti tidak ada IntelliSense atau validasi waktu kompilasi untuk itu. Ekspresi dievaluasi pada durasi. Ketika panggilan metode dijalankan, SignalR mengirim nama metode dan nilai parameter ke klien, dan jika klien memiliki metode yang cocok dengan nama, metode tersebut dipanggil dan nilai parameter diteruskan ke dalamnya. Jika tidak ada metode pencocokan yang ditemukan pada klien, tidak ada kesalahan yang muncul. Untuk informasi tentang format data yang ditransmisikan SignalR ke klien di belakang layar saat Anda memanggil metode klien, lihat Pengantar SignalR.

Pencocokan nama metode yang tidak peka huruf besar/kecil

Pencocokan nama metode tidak peka huruf besar/kecil. Misalnya, Clients.All.addContosoChatMessageToPage pada server akan menjalankan AddContosoChatMessageToPage, , addcontosochatmessagetopageatau addContosoChatMessageToPage pada klien.

Eksekusi asinkron

Metode yang Anda panggil dijalankan secara asinkron. Kode apa pun yang muncul setelah panggilan metode ke klien akan segera dijalankan tanpa menunggu SignalR selesai mengirimkan data ke klien kecuali Anda menentukan bahwa baris kode berikutnya harus menunggu penyelesaian metode. Contoh kode berikut menunjukkan cara menjalankan dua metode klien secara berurutan, satu menggunakan kode yang berfungsi di .NET 4.5, dan satu menggunakan kode yang berfungsi di .NET 4.

Contoh .NET 4.5

async public Task NewContosoChatMessage(string name, string message)
{
    await Clients.Others.addContosoChatMessageToPage(data);
    Clients.Caller.notifyMessageSent();
}

Contoh .NET 4

public void NewContosoChatMessage(string name, string message)
{
    (Clients.Others.addContosoChatMessageToPage(data) as Task).ContinueWith(antecedent =>
        Clients.Caller.notifyMessageSent());
}

Jika Anda menggunakan await atau ContinueWith menunggu hingga metode klien selesai sebelum baris kode berikutnya dijalankan, itu tidak berarti bahwa klien akan benar-benar menerima pesan sebelum baris kode berikutnya dijalankan. "Penyelesaian" dari panggilan metode klien hanya berarti bahwa SignalR telah melakukan semua yang diperlukan untuk mengirim pesan. Jika Anda memerlukan verifikasi bahwa klien menerima pesan, Anda harus memprogram mekanisme itu sendiri. Misalnya, Anda dapat membuat MessageReceived kode metode di Hub, dan dalam addContosoChatMessageToPage metode pada klien yang dapat Anda panggil MessageReceived setelah Anda melakukan pekerjaan apa pun yang perlu Anda lakukan pada klien. Di MessageReceived Hub, Anda dapat melakukan pekerjaan apa pun tergantung pada penerimaan klien yang sebenarnya dan pemrosesan panggilan metode asli.

Cara menggunakan variabel string sebagai nama metode

Jika Anda ingin memanggil metode klien dengan menggunakan variabel string sebagai nama metode, transmisikan Clients.All (atau Clients.Others, , Clients.Callerdll.) ke IClientProxy lalu panggil Invoke(methodName, args...).

public void NewContosoChatMessage(string name, string message)
{
    string methodToCall = "addContosoChatMessageToPage";
    IClientProxy proxy = Clients.All;
    proxy.Invoke(methodToCall, name, message);
}

Cara mengelola keanggotaan grup dari kelas Hub

Grup di SignalR menyediakan metode untuk menyiarkan pesan ke subset tertentu dari klien yang terhubung. Grup dapat memiliki sejumlah klien, dan klien dapat menjadi anggota dari sejumlah grup.

Untuk mengelola keanggotaan grup, gunakan metode Tambahkan dan Hapus yang disediakan oleh Groups properti kelas Hub. Contoh berikut menunjukkan Groups.Add metode dan Groups.Remove yang digunakan dalam metode Hub yang dipanggil oleh kode klien, diikuti oleh kode klien JavaScript yang memanggilnya.

Server

public class ContosoChatHub : Hub
{
    public Task JoinGroup(string groupName)
    {
        return Groups.Add(Context.ConnectionId, groupName);
    }

    public Task LeaveGroup(string groupName)
    {
        return Groups.Remove(Context.ConnectionId, groupName);
    }
}

Klien JavaScript menggunakan proksi yang dihasilkan

contosoChatHubProxy.server.joinGroup(groupName);
contosoChatHubProxy.server.leaveGroup(groupName);

Anda tidak perlu membuat grup secara eksplisit. Akibatnya grup secara otomatis dibuat saat pertama kali Anda menentukan namanya dalam panggilan ke Groups.Add, dan grup dihapus saat Anda menghapus koneksi terakhir dari keanggotaan di dalamnya.

Tidak ada API untuk mendapatkan daftar keanggotaan grup atau daftar grup. SignalR mengirim pesan ke klien dan grup berdasarkan model pub/sub, dan server tidak mempertahankan daftar grup atau keanggotaan grup. Ini membantu memaksimalkan skalabilitas, karena setiap kali Anda menambahkan simpul ke farm web, status apa pun yang dipertahankan SignalR harus disebarluaskan ke simpul baru.

Eksekusi asinkron metode Tambahkan dan Hapus

Metode Groups.Add dan Groups.Remove dijalankan secara asinkron. Jika Anda ingin menambahkan klien ke grup dan segera mengirim pesan ke klien dengan menggunakan grup, Anda harus memastikan bahwa Groups.Add metode selesai terlebih dahulu. Contoh kode berikut menunjukkan cara melakukannya, satu dengan menggunakan kode yang berfungsi di .NET 4.5, dan satu dengan menggunakan kode yang berfungsi di .NET 4

Contoh .NET 4.5

async public Task JoinGroup(string groupName)
{
    await Groups.Add(Context.ConnectionId, groupName);
    Clients.Group(groupname).addContosoChatMessageToPage(Context.ConnectionId + " added to group");
}

Contoh .NET 4

public void JoinGroup(string groupName)
{
    (Groups.Add(Context.ConnectionId, groupName) as Task).ContinueWith(antecedent =>
        Clients.Group(groupName).addContosoChatMessageToPage(Context.ConnectionId + " added to group"));
}

Persistensi keanggotaan grup

SignalR melacak koneksi, bukan pengguna, jadi jika Anda ingin pengguna berada dalam grup yang sama setiap kali pengguna membuat koneksi, Anda harus memanggil Groups.Add setiap kali pengguna membuat koneksi baru.

Setelah hilangnya konektivitas sementara, terkadang SignalR dapat memulihkan koneksi secara otomatis. Dalam hal ini, SignalR memulihkan koneksi yang sama, tidak membuat koneksi baru, sehingga keanggotaan grup klien secara otomatis dipulihkan. Ini dimungkinkan bahkan ketika jeda sementara adalah hasil dari reboot atau kegagalan server, karena status koneksi untuk setiap klien, termasuk keanggotaan grup, disandingkan dengan klien. Jika server tidak berfungsi dan digantikan oleh server baru sebelum waktu koneksi habis, klien dapat terhubung kembali secara otomatis ke server baru dan mendaftar kembali dalam grup tempat server tersebut menjadi anggotanya.

Ketika koneksi tidak dapat dipulihkan secara otomatis setelah hilangnya konektivitas, atau ketika koneksi habis, atau ketika klien terputus (misalnya, ketika browser menavigasi ke halaman baru), keanggotaan grup hilang. Lain kali pengguna tersambung akan menjadi koneksi baru. Untuk mempertahankan keanggotaan grup ketika pengguna yang sama membuat koneksi baru, aplikasi Anda harus melacak asosiasi antara pengguna dan grup, dan memulihkan keanggotaan grup setiap kali pengguna membuat koneksi baru.

Untuk informasi selengkapnya tentang koneksi dan koneksi ulang, lihat Cara menangani peristiwa seumur hidup koneksi di kelas Hub nanti dalam topik ini.

Grup pengguna tunggal

Aplikasi yang menggunakan SignalR biasanya harus melacak hubungan antara pengguna dan koneksi untuk mengetahui pengguna mana yang telah mengirim pesan dan pengguna mana yang harus menerima pesan. Grup digunakan dalam salah satu dari dua pola yang umum digunakan untuk melakukan itu.

  • Grup pengguna tunggal.

    Anda dapat menentukan nama pengguna sebagai nama grup, dan menambahkan ID koneksi saat ini ke grup setiap kali pengguna tersambung atau tersambung kembali. Untuk mengirim pesan kepada pengguna yang Anda kirim ke grup. Kerugian dari metode ini adalah bahwa grup tidak memberi Anda cara untuk mengetahui apakah pengguna online atau offline.

  • Lacak asosiasi antara nama pengguna dan ID koneksi.

    Anda dapat menyimpan hubungan antara setiap nama pengguna dan satu atau beberapa ID koneksi dalam kamus atau database, dan memperbarui data yang disimpan setiap kali pengguna tersambung atau terputus. Untuk mengirim pesan kepada pengguna, Anda menentukan ID koneksi. Kerugian dari metode ini adalah membutuhkan lebih banyak memori.

Cara menangani peristiwa seumur hidup koneksi di kelas Hub

Alasan umum untuk menangani peristiwa seumur hidup koneksi adalah untuk melacak apakah pengguna terhubung atau tidak, dan untuk melacak hubungan antara nama pengguna dan ID koneksi. Untuk menjalankan kode Anda sendiri saat klien terhubung atau memutuskan sambungan, ganti OnConnectedmetode virtual , OnDisconnected, dan OnReconnected kelas Hub, seperti yang ditunjukkan dalam contoh berikut.

public class ContosoChatHub : Hub
{
    public override Task OnConnected()
    {
        // Add your own code here.
        // For example: in a chat application, record the association between
        // the current connection ID and user name, and mark the user as online.
        // After the code in this method completes, the client is informed that
        // the connection is established; for example, in a JavaScript client,
        // the start().done callback is executed.
        return base.OnConnected();
    }

    public override Task OnDisconnected()
    {
        // Add your own code here.
        // For example: in a chat application, mark the user as offline, 
        // delete the association between the current connection id and user name.
        return base.OnDisconnected();
    }

    public override Task OnReconnected()
    {
        // Add your own code here.
        // For example: in a chat application, you might have marked the
        // user as offline after a period of inactivity; in that case 
        // mark the user as online again.
        return base.OnReconnected();
    }
}

Ketika OnConnected, OnDisconnected, dan OnReconnected dipanggil

Setiap kali browser menavigasi ke halaman baru, koneksi baru harus dibuat, yang berarti SignalR akan menjalankan OnDisconnected metode diikuti dengan OnConnected metode . SignalR selalu membuat ID koneksi baru saat koneksi baru dibuat.

Metode OnReconnected ini dipanggil ketika telah ada pemutusan sementara dalam konektivitas yang dapat dipulihkan oleh SignalR secara otomatis, seperti ketika kabel untuk sementara terputus dan terhubung kembali sebelum waktu koneksi habis. Metode OnDisconnected ini dipanggil ketika klien terputus dan SignalR tidak dapat terhubung kembali secara otomatis, seperti ketika browser menavigasi ke halaman baru. Oleh karena itu, urutan peristiwa yang mungkin untuk klien tertentu adalah OnConnected, , OnReconnectedOnDisconnected; atau OnConnected, OnDisconnected. Anda tidak akan melihat urutan OnConnected, , OnDisconnectedOnReconnected untuk koneksi tertentu.

Metode OnDisconnected ini tidak dipanggil dalam beberapa skenario, seperti ketika server tidak berfungsi atau Domain Aplikasi didaur ulang. Ketika server lain tersambung atau Domain Aplikasi menyelesaikan daur ulangnya, beberapa klien mungkin dapat menyambungkan kembali dan mengaktifkan peristiwa tersebut OnReconnected .

Untuk informasi selengkapnya, lihat Memahami dan Menangani Peristiwa Seumur Hidup Koneksi di SignalR.

Status penelepon tidak diisi

Metode penanganan aktivitas seumur hidup koneksi dipanggil dari server, yang berarti bahwa status apa pun yang Anda masukkan ke state dalam objek pada klien tidak akan diisi di Caller properti di server. Untuk informasi tentang state objek dan Caller properti , lihat Cara meneruskan status antara klien dan kelas Hub nanti dalam topik ini.

Cara mendapatkan informasi tentang klien dari properti Konteks

Untuk mendapatkan informasi tentang klien, gunakan Context properti kelas Hub. Properti Context mengembalikan objek HubCallerContext yang menyediakan akses ke informasi berikut:

  • ID koneksi klien panggilan.

    string connectionID = Context.ConnectionId;
    

    ID koneksi adalah GUID yang ditetapkan oleh SignalR (Anda tidak dapat menentukan nilai dalam kode Anda sendiri). Ada satu ID koneksi untuk setiap koneksi, dan ID koneksi yang sama digunakan oleh semua Hub jika Anda memiliki beberapa Hub di aplikasi Anda.

  • Data header HTTP.

    System.Collections.Specialized.NameValueCollection headers = Context.Request.Headers;
    

    Anda juga bisa mendapatkan header HTTP dari Context.Headers. Alasan untuk beberapa referensi ke hal yang sama adalah yang Context.Headers dibuat terlebih dahulu, Context.Request properti ditambahkan nanti, dan Context.Headers dipertahankan untuk kompatibilitas mundur.

  • Mengkueri data string.

    System.Collections.Specialized.NameValueCollection queryString = Context.Request.QueryString;
    string parameterValue = queryString["parametername"]
    

    Anda juga bisa mendapatkan data string kueri dari Context.QueryString.

    String kueri yang Anda dapatkan di properti ini adalah string yang digunakan dengan permintaan HTTP yang membuat koneksi SignalR. Anda dapat menambahkan parameter string kueri di klien dengan mengonfigurasi koneksi, yang merupakan cara mudah untuk meneruskan data tentang klien dari klien ke server. Contoh berikut menunjukkan salah satu cara untuk menambahkan string kueri di klien JavaScript saat Anda menggunakan proksi yang dihasilkan.

    $.connection.hub.qs = { "version" : "1.0" };
    

    Untuk informasi selengkapnya tentang mengatur parameter string kueri, lihat panduan API untuk klien JavaScript dan .NET .

    Anda dapat menemukan metode transportasi yang digunakan untuk koneksi dalam data string kueri, bersama dengan beberapa nilai lain yang digunakan secara internal oleh SignalR:

    string transportMethod = queryString["transport"];
    

    Nilainya transportMethod adalah "webSockets", "serverSentEvents", "foreverFrame" atau "longPolling". Perhatikan bahwa jika Anda memeriksa nilai ini dalam OnConnected metode penanganan aktivitas, dalam beberapa skenario, Anda mungkin awalnya mendapatkan nilai transportasi yang bukan metode transportasi akhir yang dinegosiasikan untuk koneksi. Dalam hal ini metode akan melemparkan pengecualian dan akan dipanggil lagi nanti ketika metode transportasi akhir ditetapkan.

  • Cookie.

    System.Collections.Generic.IDictionary<string, Cookie> cookies = Context.Request.Cookies;
    

    Anda juga bisa mendapatkan cookie dari Context.RequestCookies.

  • Informasi pengguna.

    System.Security.Principal.IPrincipal user = Context.User;
    
  • Objek HttpContext untuk permintaan :

    System.Web.HttpContextBase httpContext = Context.Request.GetHttpContext();
    

    Gunakan metode ini alih-alih HttpContext.Current mendapatkan HttpContext objek untuk koneksi SignalR.

Cara melewati status antara klien dan kelas Hub

Proksi klien menyediakan state objek tempat Anda dapat menyimpan data yang ingin Anda kirimkan ke server dengan setiap panggilan metode. Di server Anda dapat mengakses data ini di Clients.Caller properti dalam metode Hub yang dipanggil oleh klien. Properti Clients.Caller tidak diisi untuk metode OnConnectedpenanganan aktivitas seumur hidup koneksi , , OnDisconnecteddan OnReconnected.

Membuat atau memperbarui data dalam state objek dan Clients.Caller properti berfungsi di kedua arah. Anda dapat memperbarui nilai di server dan nilai tersebut diteruskan kembali ke klien.

Contoh berikut menunjukkan kode klien JavaScript yang menyimpan status untuk transmisi ke server dengan setiap panggilan metode.

contosoChatHubProxy.state.userName = "Fadi Fakhouri";
contosoChatHubProxy.state.computerName = "fadivm1";

Contoh berikut menunjukkan kode yang setara dalam klien .NET.

contosoChatHubProxy["userName"] = "Fadi Fakhouri";
chatHubProxy["computerName"] = "fadivm1";

Di kelas Hub, Anda dapat mengakses data ini di Clients.Caller properti . Contoh berikut menunjukkan kode yang mengambil status yang dimaksud dalam contoh sebelumnya.

public void NewContosoChatMessage(string data)
{
    string userName = Clients.Caller.userName;
    string computerName = Clients.Caller.computerName;
    Clients.Others.addContosoChatMessageToPage(message, userName, computerName);
}

Catatan

Mekanisme untuk status bertahan ini tidak ditujukan untuk data dalam jumlah besar, karena semua yang Anda masukkan ke state dalam properti atau Clients.Caller disandingkan dengan setiap pemanggilan metode. Ini berguna untuk item yang lebih kecil seperti nama pengguna atau penghitung.

Cara menangani kesalahan di kelas Hub

Untuk menangani kesalahan yang terjadi di metode kelas Hub Anda, gunakan salah satu atau kedua metode berikut:

  • Bungkus kode metode Anda di blok try-catch dan catat objek pengecualian. Untuk tujuan penelusuran kesalahan, Anda dapat mengirim pengecualian ke klien, tetapi untuk alasan keamanan mengirim informasi terperinci kepada klien dalam produksi tidak disarankan.

  • Buat modul alur Hubs yang menangani metode OnIncomingError . Contoh berikut menunjukkan modul alur yang mencatat kesalahan, diikuti oleh kode di Global.asax yang menyuntikkan modul ke dalam alur Hubs.

    public class ErrorHandlingPipelineModule : HubPipelineModule
    {
        protected override void OnIncomingError(Exception ex, IHubIncomingInvokerContext context)
        {
            Debug.WriteLine("=> Exception " + ex.Message);
            if (ex.InnerException != null)
            {
                Debug.WriteLine("=> Inner Exception " + ex.InnerException.Message);
            }
            base.OnIncomingError(ex, context);
        }
    }
    
    protected void Application_Start(object sender, EventArgs e)
    {
        GlobalHost.HubPipeline.AddModule(new ErrorHandlingPipelineModule()); 
        RouteTable.Routes.MapHubs();
    }
    

Untuk informasi selengkapnya tentang modul alur Hub, lihat Cara menyesuaikan alur Hub nanti dalam topik ini.

Cara mengaktifkan pelacakan

Untuk mengaktifkan pelacakan sisi server, tambahkan elemen system.diagnostics ke file Web.config Anda, seperti yang ditunjukkan dalam contoh ini:

<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit https://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <connectionStrings>
    <add name="SignalRSamples" connectionString="Data Source=(local);Initial Catalog=SignalRSamples;Integrated Security=SSPI;Asynchronous Processing=True;" />
    <add name="SignalRSamplesWithMARS" connectionString="Data Source=(local);Initial Catalog=SignalRSamples;Integrated Security=SSPI;Asynchronous Processing=True;MultipleActiveResultSets=true;" />
  </connectionStrings>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
  </system.web>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
  </system.webServer>
  <system.diagnostics>
    <sources>
      <source name="SignalR.SqlMessageBus">
        <listeners>
          <add name="SignalR-Bus" />
        </listeners>
      </source>
     <source name="SignalR.ServiceBusMessageBus">
        <listeners>
            <add name="SignalR-Bus" />
        </listeners>
     </source>
     <source name="SignalR.ScaleoutMessageBus">
        <listeners>
            <add name="SignalR-Bus" />
        </listeners>
      </source>
      <source name="SignalR.Transports.WebSocketTransport">
        <listeners>
          <add name="SignalR-Transports" />
        </listeners>
      </source>
      <source name="SignalR.Transports.ServerSentEventsTransport">
          <listeners>
              <add name="SignalR-Transports" />
          </listeners>
      </source>
      <source name="SignalR.Transports.ForeverFrameTransport">
          <listeners>
              <add name="SignalR-Transports" />
          </listeners>
      </source>
      <source name="SignalR.Transports.LongPollingTransport">
        <listeners>
            <add name="SignalR-Transports" />
        </listeners>
      </source>
      <source name="SignalR.Transports.TransportHeartBeat">
        <listeners>
            <add name="SignalR-Transports" />
        </listeners>
      </source>
    </sources>
    <switches>
      <add name="SignalRSwitch" value="Verbose" />
    </switches>
    <sharedListeners>
      <add name="SignalR-Transports" 
           type="System.Diagnostics.TextWriterTraceListener" 
           initializeData="transports.log.txt" />
        <add name="SignalR-Bus"
           type="System.Diagnostics.TextWriterTraceListener"
           initializeData="bus.log.txt" />
    </sharedListeners>
    <trace autoflush="true" />
  </system.diagnostics>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v11.0" />
      </parameters>
    </defaultConnectionFactory>
  </entityFramework>
</configuration>

Saat menjalankan aplikasi di Visual Studio, Anda dapat melihat log di jendela Output .

Cara memanggil metode klien dan mengelola grup dari luar kelas Hub

Untuk memanggil metode klien dari kelas yang berbeda dari kelas Hub Anda, dapatkan referensi ke objek konteks SignalR untuk Hub dan gunakan itu untuk memanggil metode pada klien atau mengelola grup.

Kelas sampel StockTicker berikut mendapatkan objek konteks, menyimpannya dalam instans kelas, menyimpan instans kelas dalam properti statis, dan menggunakan konteks dari instans kelas singleton untuk memanggil updateStockPrice metode pada klien yang terhubung ke Hub bernama StockTickerHub.

// For the complete example, go to 
// http://www.asp.net/signalr/overview/signalr-1x/getting-started/tutorial-server-broadcast-with-aspnet-signalr
// This sample only shows code related to getting and using the SignalR context.
public class StockTicker
{
    // Singleton instance
    private readonly static Lazy<StockTicker> _instance = new Lazy<StockTicker>(
        () => new StockTicker(GlobalHost.ConnectionManager.GetHubContext<StockTickerHub>()));

    private IHubContext _context;

    private StockTicker(IHubContext context)
    {
        _context = context;
    }

    // This method is invoked by a Timer object.
    private void UpdateStockPrices(object state)
    {
        foreach (var stock in _stocks.Values)
        {
            if (TryUpdateStockPrice(stock))
            {
                _context.Clients.All.updateStockPrice(stock);
            }
        }
    }

Jika Anda perlu menggunakan konteks beberapa kali dalam objek berumur panjang, dapatkan referensi sekali dan simpan daripada mendapatkannya lagi setiap kali. Mendapatkan konteks setelah memastikan bahwa SignalR mengirim pesan ke klien dalam urutan yang sama di mana metode Hub Anda membuat pemanggilan metode klien. Untuk tutorial yang menunjukkan cara menggunakan konteks SignalR untuk Hub, lihat Siaran Server dengan ASP.NET SignalR.

Memanggil metode klien

Anda dapat menentukan klien mana yang akan menerima RPC, tetapi Anda memiliki lebih sedikit opsi daripada saat Anda memanggil dari kelas Hub. Alasan untuk ini adalah bahwa konteksnya tidak terkait dengan panggilan tertentu dari klien, sehingga metode apa pun yang memerlukan pengetahuan tentang ID koneksi saat ini, seperti Clients.Others, atau Clients.Caller, atau Clients.OthersInGroup, tidak tersedia. Opsi berikut tersedia:

  • Semua klien yang terhubung.

    context.Clients.All.addContosoChatMessageToPage(name, message);
    
  • Klien tertentu yang diidentifikasi oleh ID koneksi.

    context.Clients.Client(connectionID).addContosoChatMessageToPage(name, message);
    
  • Semua klien yang terhubung kecuali klien yang ditentukan, diidentifikasi oleh ID koneksi.

    context.Clients.AllExcept(connectionId1, connectionId2).addContosoChatMessageToPage(name, message);
    
  • Semua klien yang terhubung dalam grup tertentu.

    context.Clients.Group(groupName).addContosoChatMessageToPage(name, message);
    
  • Semua klien yang terhubung dalam grup tertentu kecuali klien tertentu, yang diidentifikasi oleh ID koneksi.

    Clients.Group(groupName, connectionId1, connectionId2).addContosoChatMessageToPage(name, message);
    

Jika Anda memanggil kelas non-Hub dari metode di kelas Hub, Anda dapat meneruskan ID koneksi saat ini dan menggunakannya dengan Clients.Client, , atau Clients.Group untuk mensimulasikan Clients.Caller, , Clients.Othersatau Clients.OthersInGroupClients.AllExcept. Dalam contoh berikut, MoveShapeHub kelas meneruskan ID koneksi ke Broadcaster kelas sehingga Broadcaster kelas dapat mensimulasikan Clients.Others.

// For the complete example, see
// http://www.asp.net/signalr/overview/getting-started/tutorial-high-frequency-realtime-with-signalr
// This sample only shows code that passes connection ID to the non-Hub class,
// in order to simulate Clients.Others.
public class MoveShapeHub : Hub
{
    // Code not shown puts a singleton instance of Broadcaster in this variable.
    private Broadcaster _broadcaster;

    public void UpdateModel(ShapeModel clientModel)
    {
        clientModel.LastUpdatedBy = Context.ConnectionId;
        // Update the shape model within our broadcaster
        _broadcaster.UpdateShape(clientModel);
    }
}

public class Broadcaster
{
    public Broadcaster()
    {
        _hubContext = GlobalHost.ConnectionManager.GetHubContext<MoveShapeHub>();
    }

    public void UpdateShape(ShapeModel clientModel)
    {
        _model = clientModel;
        _modelUpdated = true;
    }

    // Called by a Timer object.
    public void BroadcastShape(object state)
    {
        if (_modelUpdated)
        {
            _hubContext.Clients.AllExcept(_model.LastUpdatedBy).updateShape(_model);
            _modelUpdated = false;
        }
    }
}

Mengelola keanggotaan grup

Untuk mengelola grup, Anda memiliki opsi yang sama seperti yang Anda lakukan di kelas Hub.

  • Menambahkan klien ke grup

    context.Groups.Add(connectionID, groupName);
    
  • Menghapus klien dari grup

    context.Groups.Remove(connectionID, groupName);
    

Cara menyesuaikan alur Hub

SignalR memungkinkan Anda untuk menyuntikkan kode Anda sendiri ke dalam alur Hub. Contoh berikut menunjukkan modul alur Hub kustom yang mencatat setiap panggilan metode masuk yang diterima dari klien dan panggilan metode keluar yang dipanggil pada klien:

public class LoggingPipelineModule : HubPipelineModule 
{ 
    protected override bool OnBeforeIncoming(IHubIncomingInvokerContext context) 
    { 
        Debug.WriteLine("=> Invoking " + context.MethodDescriptor.Name + " on hub " + context.MethodDescriptor.Hub.Name); 
        return base.OnBeforeIncoming(context); 
    }   
    protected override bool OnBeforeOutgoing(IHubOutgoingInvokerContext context) 
    { 
        Debug.WriteLine("<= Invoking " + context.Invocation.Method + " on client hub " + context.Invocation.Hub); 
        return base.OnBeforeOutgoing(context); 
    } 
}

Kode berikut dalam file Global.asax mendaftarkan modul untuk dijalankan di alur Hub:

protected void Application_Start(object sender, EventArgs e) 
{ 
    GlobalHost.HubPipeline.AddModule(new LoggingPipelineModule()); 
    RouteTable.Routes.MapHubs();
}

Ada banyak metode berbeda yang dapat Anda ambil alih. Untuk daftar lengkapnya, lihat Metode HubPipelineModule.