ASP.NET Core için hub'ları SignalR kullanma

Tarafından Rachel Appel ve Kevin Griffin

Hubs API'si SignalR , bağlı istemcilerin sunucudaki yöntemleri çağırarak gerçek zamanlı iletişimi kolaylaştırmalarına olanak tanır. Sunucu, istemci tarafından çağrılan yöntemleri, istemci ise sunucu tarafından çağrılan yöntemleri tanımlar. SignalR ayrıca, her zaman Hub tarafından aracılık edilen dolaylı istemciden istemciye iletişimi etkinleştirir ve iletilerin SignalR tek tek istemciler, gruplar veya tüm bağlı istemcilere gönderilmesine olanak tanır. SignalR gerçek zamanlı istemciden sunucuya ve sunucudan istemciye iletişimi mümkün kılmak için gereken her şeyi gerçekleştirir.

Hub'ları yapılandırma SignalR

Hub'lar AddSignalR için SignalR gereken hizmetleri kaydetmek için çağrısında:Program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddSignalR();

Uç noktaları yapılandırmak SignalR için içinde de öğesini çağırabilirsinizProgram.csMapHub:

app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");

app.Run();

Not

ASP.NET Core SignalR sunucu tarafı derlemeleri artık .NET Core SDK ile yüklenir. Daha fazla bilgi için bkz SignalR . Paylaşılan çerçevedeki derlemeler.

Hub oluşturma ve kullanma

öğesinden Hubdevralan bir sınıf bildirerek bir hub oluşturun. İstemcilerden çağrılabilen hale getirmek için sınıfına yöntemler ekleyin public :

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
        => await Clients.All.SendAsync("ReceiveMessage", user, message);
}

Not

Hub'lar geçicidir:

  • Durumu hub sınıfının bir özelliğinde depolamayın. Her hub yöntemi çağrısı yeni bir hub örneğinde yürütülür.
  • Bağımlılık ekleme yoluyla doğrudan hub örneği oluşturmayın. Uygulamanızın başka bir yerinden bir istemciye ileti göndermek için kullanın IHubContext.
  • Hub'ın hayatta kalmasına bağlı zaman uyumsuz yöntemleri çağırırken kullanın await . Örneğin, gibi Clients.All.SendAsync(...) bir yöntem olmadan await çağrılırsa ve hub yöntemi tamamlanmadan önce SendAsync tamamlanırsa başarısız olabilir.

Context nesnesi

sınıfı, Hub bağlantı hakkında bilgi içeren aşağıdaki özellikleri içeren bir Context özellik içerir:

Özellik Açıklama
ConnectionId Bağlantının tarafından SignalRatanan benzersiz kimliğini alır. Her bağlantı için bir bağlantı kimliği vardır.
UserIdentifier Kullanıcı tanımlayıcısını alır. Varsayılan olarak, SignalR kullanıcı tanımlayıcısı olarak bağlantıyla ilişkilendirilmiş olan öğesini ClaimsPrincipal kullanırClaimTypes.NameIdentifier.
User ClaimsPrincipal Geçerli kullanıcıyla ilişkili olan öğesini alır.
Items Bu bağlantı kapsamında veri paylaşmak için kullanılabilecek bir anahtar/değer koleksiyonu alır. Veriler bu koleksiyonda depolanabilir ve farklı hub yöntemi çağrıları arasında bağlantı için kalıcı olur.
Features Bağlantıda kullanılabilen özellik koleksiyonunu alır. Şimdilik bu koleksiyon çoğu senaryoda gerekli olmadığından henüz ayrıntılı olarak belgelenmemiştir.
ConnectionAborted Bağlantı durdurulduğunda bunu bildiren bir CancellationToken alır.

Hub.Context ayrıca aşağıdaki yöntemleri içerir:

Metot Açıklama
GetHttpContext HttpContext Bağlantının veya bağlantının null bir HTTP isteğiyle ilişkilendirilip ilişkilendirnmediğini döndürür. HTTP bağlantıları için, HTTP üst bilgileri ve sorgu dizeleri gibi bilgileri almak için bu yöntemi kullanın.
Abort Bağlantıyı durdurur.

İstemciler nesnesi

sınıfı, Hub sunucu ve istemci arasındaki iletişim için aşağıdaki özellikleri içeren bir Clients özellik içerir:

Özellik Açıklama
All Tüm bağlı istemcilerde bir yöntemi çağırır
Caller İstemcide hub yöntemini çağıran bir yöntemi çağırır
Others Yöntemini çağıran istemci dışındaki tüm bağlı istemcilerde bir yöntemi çağırır

Hub.Clients ayrıca aşağıdaki yöntemleri içerir:

Metot Açıklama
AllExcept Belirtilen bağlantılar dışında tüm bağlı istemcilerde bir yöntemi çağırır
Client Belirli bir bağlı istemcide bir yöntemi çağırır
Clients Belirli bağlı istemcilerde bir yöntemi çağırır
Group Belirtilen gruptaki tüm bağlantılarda bir yöntemi çağırır
GroupExcept Belirtilen bağlantılar dışında belirtilen gruptaki tüm bağlantılarda bir yöntemi çağırır
Groups Birden çok bağlantı grubunda bir yöntemi çağırır
OthersInGroup Hub yöntemini çağıran istemci hariç olmak üzere bir bağlantı grubundaki bir yöntemi çağırır
User Belirli bir kullanıcıyla ilişkili tüm bağlantılarda bir yöntemi çağırır
Users Belirtilen kullanıcılarla ilişkili tüm bağlantılarda bir yöntemi çağırır

Yukarıdaki tablolardaki her özellik veya yöntem, yöntemi olan bir SendAsync nesne döndürür. yöntemi, SendAsync çağrılacak istemci yönteminin adını ve tüm parametreleri alır.

ve Caller yöntemleri tarafından Client döndürülen nesne, istemciden bir sonuç beklemek için kullanılabilecek bir InvokeAsync yöntem de içerir.

İstemcilere ileti gönderme

Belirli istemcilere çağrı yapmak için nesnesinin Clients özelliklerini kullanın. Aşağıdaki örnekte üç hub yöntemi vardır:

  • SendMessage kullanarak Clients.Alltüm bağlı istemcilere bir ileti gönderir.
  • SendMessageToCaller kullanarak Clients.Callerçağırana bir ileti gönderir.
  • SendMessageToGroup gruptaki SignalR Users tüm istemcilere bir ileti gönderir.
public async Task SendMessage(string user, string message)
    => await Clients.All.SendAsync("ReceiveMessage", user, message);

public async Task SendMessageToCaller(string user, string message)
    => await Clients.Caller.SendAsync("ReceiveMessage", user, message);

public async Task SendMessageToGroup(string user, string message)
    => await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);

Kesin türemiş hub'lar

kullanmanın SendAsync bir dezavantajı, çağrılacak istemci yöntemini belirtmek için bir dizeye bağlı olmasıdır. Bu, yöntem adı yanlış yazılmışsa veya istemcide eksikse kodu çalışma zamanı hatalarına açık bırakır.

kullanmanın SendAsync bir alternatifi, sınıfını Hub ile Hub<T>güçlü bir şekilde yazmaktır. Aşağıdaki örnekte, ChatHub istemci yöntemi adlı IChatClientbir arabirimde ayıklanmıştır:

public interface IChatClient
{
    Task ReceiveMessage(string user, string message);
}

Bu arabirim, önceki ChatHub örneği kesin olarak yazılacak şekilde yeniden düzenleme amacıyla kullanılabilir:

public class StronglyTypedChatHub : Hub<IChatClient>
{
    public async Task SendMessage(string user, string message)
        => await Clients.All.ReceiveMessage(user, message);

    public async Task SendMessageToCaller(string user, string message)
        => await Clients.Caller.ReceiveMessage(user, message);

    public async Task SendMessageToGroup(string user, string message)
        => await Clients.Group("SignalR Users").ReceiveMessage(user, message);
}

kullanarak Hub<IChatClient> istemci yöntemlerinin derleme zamanı denetimini etkinleştirir. Bu, Hub<T> yalnızca arabirimde tanımlanan yöntemlere erişim sağlayabildiği için dizelerin kullanılmasından kaynaklanan sorunları önler. Kesin olarak yazılan Hub<T> bir kullanmak, özelliğini kullanma SendAsyncözelliğini devre dışı bırakır.

Not

Sonek Async , yöntem adlarından çıkarılmamış. ile .on('MyMethodAsync')bir istemci yöntemi tanımlanmadığı sürece, ad olarak kullanmayın MyMethodAsync .

İstemci sonuçları

sunucu, istemcilere çağrı yapmaya ek olarak bir istemciden sonuç isteyebilir. Bunun için sunucunun kullanması ISingleClientProxy.InvokeAsync ve istemcinin işleyicisinden bir sonuç döndürmesi .On gerekir.

API'yi sunucuda kullanmanın iki yolu vardır; birincisi hub yönteminde veya Caller özelliğinde Clients çağırmaktırClient(...):

public class ChatHub : Hub
{
    public async Task<string> WaitForMessage(string connectionId)
    {
        var message = await Clients.Client(connectionId).InvokeAsync<string>(
            "GetMessage");
        return message;
    }
}

İkinci yol, örneğinde çağrısı Client(...) yapmaktır IHubContext<T>:

async Task SomeMethod(IHubContext<MyHub> context)
{
    string result = await context.Clients.Client(connectionID).InvokeAsync<string>(
        "GetMessage");
}

Kesin türe sahip hub'lar, arabirim yöntemlerinden de değer döndürebilir:

public interface IClient
{
    Task<string> GetMessage();
}

public class ChatHub : Hub<IClient>
{
    public async Task<string> WaitForMessage(string connectionId)
    {
        string message = await Clients.Client(connectionId).GetMessage();
        return message;
    }
}

İstemciler aşağıda gösterildiği gibi sonuçları işleyicilerinde .On(...) döndürür:

.NET istemcisi

hubConnection.On("GetMessage", async () =>
{
    Console.WriteLine("Enter message:");
    var message = await Console.In.ReadLineAsync();
    return message;
});

Typescript istemcisi

hubConnection.on("GetMessage", async () => {
    let promise = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("message");
        }, 100);
    });
    return promise;
});

Java istemcisi

hubConnection.onWithResult("GetMessage", () -> {
    return Single.just("message");
});

Hub yönteminin adını değiştirme

Varsayılan olarak, sunucu hub'ı yöntemi adı .NET yönteminin adıdır. Belirli bir yöntemin bu varsayılan davranışını değiştirmek için HubMethodName özniteliğini kullanın. İstemci, yöntemini çağırırken .NET yöntemi adı yerine bu adı kullanmalıdır:

[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
    => await Clients.User(user).SendAsync("ReceiveMessage", user, message);

Hub'a hizmet ekleme

Hub oluşturucuları, DI'den gelen hizmetleri parametre olarak kabul edebilir ve bu hizmetler bir hub yönteminde kullanılmak üzere sınıfındaki özelliklerde depolanabilir.

Farklı hub yöntemleri için veya kod yazmanın alternatif bir yolu olarak birden çok hizmet eklerken, hub yöntemleri DI'den gelen hizmetleri de kabul edebilir. Varsayılan olarak, hub yöntemi parametreleri mümkünse DI'den incelenir ve çözümlenir.

services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();

// ...

public class ChatHub : Hub
{
    public Task SendMessage(string user, string message, IDatabaseService dbService)
    {
        var userName = dbService.GetUserName(user);
        return Clients.All.SendAsync("ReceiveMessage", userName, message);
    }
}

Hizmetlerden gelen parametrelerin örtük çözümlemesi istenmiyorsa DisableImplicitFromServicesParameters ile devre dışı bırakın. Hub'da DI yöntemlerinden hangi parametrelerin çözümleneceğini açıkça belirtmek için seçeneğini kullanın DisableImplicitFromServicesParameters ve özniteliğini veya DI'den çözümlenmesi gereken hub yöntemi parametrelerinde uygulayan IFromServiceMetadata özel bir özniteliği kullanın[FromServices].

services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();
services.AddSignalR(options =>
{
    options.DisableImplicitFromServicesParameters = true;
});

// ...

public class ChatHub : Hub
{
    public Task SendMessage(string user, string message,
        [FromServices] IDatabaseService dbService)
    {
        var userName = dbService.GetUserName(user);
        return Clients.All.SendAsync("ReceiveMessage", userName, message);
    }
}

Not

Bu özellik, isteğe bağlı olarak DI uygulamaları tarafından uygulanan öğesini kullanır IServiceProviderIsService. Uygulamanın DI kapsayıcısı bu özelliği desteklemiyorsa, hub yöntemlerine hizmet ekleme desteklenmez.

Bağımlılık Ekleme'de anahtarlı hizmetler desteği

Anahtarlı hizmetler , anahtarları kullanarak Bağımlılık Ekleme (DI) hizmetlerini kaydetmeye ve almaya yönelik bir mekanizmayı ifade eder. Hizmet, kaydetmek için (veya AddKeyedScoped AddKeyedTransient) çağrılarak AddKeyedSingleton bir anahtarla ilişkilendirilir. özniteliğine sahip anahtarı belirterek kayıtlı bir hizmete erişin [FromKeyedServices] . Aşağıdaki kodda anahtarlı hizmetlerin nasıl kullanılacağı gösterilmektedir:

using Microsoft.AspNetCore.SignalR;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddKeyedSingleton<ICache, BigCache>("big");
builder.Services.AddKeyedSingleton<ICache, SmallCache>("small");

builder.Services.AddRazorPages();
builder.Services.AddSignalR();

var app = builder.Build();

app.MapRazorPages();
app.MapHub<MyHub>("/myHub");

app.Run();

public interface ICache
{
    object Get(string key);
}
public class BigCache : ICache
{
    public object Get(string key) => $"Resolving {key} from big cache.";
}

public class SmallCache : ICache
{
    public object Get(string key) => $"Resolving {key} from small cache.";
}

public class MyHub : Hub
{
    public void SmallCacheMethod([FromKeyedServices("small")] ICache cache)
    {
        Console.WriteLine(cache.Get("signalr"));
    }

    public void BigCacheMethod([FromKeyedServices("big")] ICache cache)
    {
        Console.WriteLine(cache.Get("signalr"));
    }
}

Bağlantı için olayları işleme

Hubs API'sinde SignalR OnConnectedAsync bağlantıları yönetmek ve izlemek için ve OnDisconnectedAsync sanal yöntemleri sağlanır. bir istemci hub'a OnConnectedAsync bağlandığında eylemleri gerçekleştirmek için sanal yöntemi geçersiz kılın; örneğin, bunu bir gruba ekleyin:

public override async Task OnConnectedAsync()
{
    await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
    await base.OnConnectedAsync();
}

İstemci bağlantısı OnDisconnectedAsync kesildiğinde eylem gerçekleştirmek için sanal yöntemi geçersiz kılın. İstemcinin bağlantısı kasıtlı olarak, örneğin çağrısıyla connection.stop()exception kesilirse, parametresi olarak nullayarlanır. Ancak, ağ hatası gibi bir hata nedeniyle istemcinin bağlantısı kesilirse, exception parametre hatayı açıklayan bir özel durum içerir:

public override async Task OnDisconnectedAsync(Exception? exception)
{
    await base.OnDisconnectedAsync(exception);
}

RemoveFromGroupAsync içinde OnDisconnectedAsyncçağrılması gerekmez. Sizin için otomatik olarak işlenir.

Hataları işleme

Hub yöntemlerinde oluşan özel durumlar, yöntemini çağıran istemciye gönderilir. JavaScript istemcisinde invoke yöntemi bir JavaScript Promisedöndürür. İstemciler döndürülen söze bir catch işleyici ekleyebilir veya özel durumları işlemek için ile/asyncawait kullanabilir:try/catch

try {
  await connection.invoke("SendMessage", user, message);
} catch (err) {
  console.error(err);
}

Bir hub özel durum oluştururken bağlantılar kapatılamaz. Varsayılan olarak, SignalR aşağıdaki örnekte gösterildiği gibi istemciye genel bir hata iletisi döndürür:

Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.

Beklenmeyen özel durumlar genellikle veritabanı bağlantısı başarısız olduğunda tetiklenen bir özel durumdaki veritabanı sunucusunun adı gibi hassas bilgiler içerir. SignalR güvenlik önlemi olarak bu ayrıntılı hata iletilerini varsayılan olarak kullanıma sunmaz. Özel durum ayrıntılarının neden gizlendiğini öğrenmek için bkz . ASP.NET Core'da SignalRgüvenlikle ilgili dikkat edilmesi gerekenler.

İstemciye olağanüstü bir koşul yayılması gerekiyorsa sınıfını HubException kullanın. HubException bir hub yönteminde oluşturulursa, SignalRözel durum iletisinin tamamını değiştirilmemiş olarak istemciye gönderir:

public Task ThrowException()
    => throw new HubException("This error will be sent to the client!");

Not

SignalR yalnızca özel durumun özelliğini istemciye gönderir Message . Özel durumdaki yığın izlemesi ve diğer özellikler istemci tarafından kullanılamaz.

Ek kaynaklar

Tarafından Rachel Appel ve Kevin Griffin

Hubs API'si SignalR , bağlı istemcilerin sunucudaki yöntemleri çağırarak gerçek zamanlı iletişimi kolaylaştırmalarına olanak tanır. Sunucu, istemci tarafından çağrılan yöntemleri, istemci ise sunucu tarafından çağrılan yöntemleri tanımlar. SignalR ayrıca, her zaman Hub tarafından aracılık edilen dolaylı istemciden istemciye iletişimi etkinleştirir ve iletilerin SignalR tek tek istemciler, gruplar veya tüm bağlı istemcilere gönderilmesine olanak tanır. SignalR gerçek zamanlı istemciden sunucuya ve sunucudan istemciye iletişimi mümkün kılmak için gereken her şeyi gerçekleştirir.

Hub'ları yapılandırma SignalR

Hub'lar AddSignalR için SignalR gereken hizmetleri kaydetmek için çağrısında:Program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddSignalR();

Uç noktaları yapılandırmak SignalR için içinde de öğesini çağırabilirsinizProgram.csMapHub:

app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");

app.Run();

Not

ASP.NET Core SignalR sunucu tarafı derlemeleri artık .NET Core SDK ile yüklenir. Daha fazla bilgi için bkz SignalR . Paylaşılan çerçevedeki derlemeler.

Hub oluşturma ve kullanma

öğesinden Hubdevralan bir sınıf bildirerek bir hub oluşturun. İstemcilerden çağrılabilen hale getirmek için sınıfına yöntemler ekleyin public :

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
        => await Clients.All.SendAsync("ReceiveMessage", user, message);
}

Not

Hub'lar geçicidir:

  • Durumu hub sınıfının bir özelliğinde depolamayın. Her hub yöntemi çağrısı yeni bir hub örneğinde yürütülür.
  • Bağımlılık ekleme yoluyla doğrudan hub örneği oluşturmayın. Uygulamanızın başka bir yerinden bir istemciye ileti göndermek için kullanın IHubContext.
  • Hub'ın hayatta kalmasına bağlı zaman uyumsuz yöntemleri çağırırken kullanın await . Örneğin, gibi Clients.All.SendAsync(...) bir yöntem olmadan await çağrılırsa ve hub yöntemi tamamlanmadan önce SendAsync tamamlanırsa başarısız olabilir.

Context nesnesi

sınıfı, Hub bağlantı hakkında bilgi içeren aşağıdaki özellikleri içeren bir Context özellik içerir:

Özellik Açıklama
ConnectionId Bağlantının tarafından SignalRatanan benzersiz kimliğini alır. Her bağlantı için bir bağlantı kimliği vardır.
UserIdentifier Kullanıcı tanımlayıcısını alır. Varsayılan olarak, SignalR kullanıcı tanımlayıcısı olarak bağlantıyla ilişkilendirilmiş olan öğesini ClaimsPrincipal kullanırClaimTypes.NameIdentifier.
User ClaimsPrincipal Geçerli kullanıcıyla ilişkili olan öğesini alır.
Items Bu bağlantı kapsamında veri paylaşmak için kullanılabilecek bir anahtar/değer koleksiyonu alır. Veriler bu koleksiyonda depolanabilir ve farklı hub yöntemi çağrıları arasında bağlantı için kalıcı olur.
Features Bağlantıda kullanılabilen özellik koleksiyonunu alır. Şimdilik bu koleksiyon çoğu senaryoda gerekli olmadığından henüz ayrıntılı olarak belgelenmemiştir.
ConnectionAborted Bağlantı durdurulduğunda bunu bildiren bir CancellationToken alır.

Hub.Context ayrıca aşağıdaki yöntemleri içerir:

Metot Açıklama
GetHttpContext HttpContext Bağlantının veya bağlantının null bir HTTP isteğiyle ilişkilendirilip ilişkilendirnmediğini döndürür. HTTP bağlantıları için, HTTP üst bilgileri ve sorgu dizeleri gibi bilgileri almak için bu yöntemi kullanın.
Abort Bağlantıyı durdurur.

İstemciler nesnesi

sınıfı, Hub sunucu ve istemci arasındaki iletişim için aşağıdaki özellikleri içeren bir Clients özellik içerir:

Özellik Açıklama
All Tüm bağlı istemcilerde bir yöntemi çağırır
Caller İstemcide hub yöntemini çağıran bir yöntemi çağırır
Others Yöntemini çağıran istemci dışındaki tüm bağlı istemcilerde bir yöntemi çağırır

Hub.Clients ayrıca aşağıdaki yöntemleri içerir:

Metot Açıklama
AllExcept Belirtilen bağlantılar dışında tüm bağlı istemcilerde bir yöntemi çağırır
Client Belirli bir bağlı istemcide bir yöntemi çağırır
Clients Belirli bağlı istemcilerde bir yöntemi çağırır
Group Belirtilen gruptaki tüm bağlantılarda bir yöntemi çağırır
GroupExcept Belirtilen bağlantılar dışında belirtilen gruptaki tüm bağlantılarda bir yöntemi çağırır
Groups Birden çok bağlantı grubunda bir yöntemi çağırır
OthersInGroup Hub yöntemini çağıran istemci hariç olmak üzere bir bağlantı grubundaki bir yöntemi çağırır
User Belirli bir kullanıcıyla ilişkili tüm bağlantılarda bir yöntemi çağırır
Users Belirtilen kullanıcılarla ilişkili tüm bağlantılarda bir yöntemi çağırır

Yukarıdaki tablolardaki her özellik veya yöntem, yöntemi olan bir SendAsync nesne döndürür. yöntemi, SendAsync çağrılacak istemci yönteminin adını ve tüm parametreleri alır.

ve Caller yöntemleri tarafından Client döndürülen nesne, istemciden bir sonuç beklemek için kullanılabilecek bir InvokeAsync yöntem de içerir.

İstemcilere ileti gönderme

Belirli istemcilere çağrı yapmak için nesnesinin Clients özelliklerini kullanın. Aşağıdaki örnekte üç hub yöntemi vardır:

  • SendMessage kullanarak Clients.Alltüm bağlı istemcilere bir ileti gönderir.
  • SendMessageToCaller kullanarak Clients.Callerçağırana bir ileti gönderir.
  • SendMessageToGroup gruptaki SignalR Users tüm istemcilere bir ileti gönderir.
public async Task SendMessage(string user, string message)
    => await Clients.All.SendAsync("ReceiveMessage", user, message);

public async Task SendMessageToCaller(string user, string message)
    => await Clients.Caller.SendAsync("ReceiveMessage", user, message);

public async Task SendMessageToGroup(string user, string message)
    => await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);

Kesin türemiş hub'lar

kullanmanın SendAsync bir dezavantajı, çağrılacak istemci yöntemini belirtmek için bir dizeye bağlı olmasıdır. Bu, yöntem adı yanlış yazılmışsa veya istemcide eksikse kodu çalışma zamanı hatalarına açık bırakır.

kullanmanın SendAsync bir alternatifi, sınıfını Hub ile Hub<T>güçlü bir şekilde yazmaktır. Aşağıdaki örnekte, ChatHub istemci yöntemi adlı IChatClientbir arabirimde ayıklanmıştır:

public interface IChatClient
{
    Task ReceiveMessage(string user, string message);
}

Bu arabirim, önceki ChatHub örneği kesin olarak yazılacak şekilde yeniden düzenleme amacıyla kullanılabilir:

public class StronglyTypedChatHub : Hub<IChatClient>
{
    public async Task SendMessage(string user, string message)
        => await Clients.All.ReceiveMessage(user, message);

    public async Task SendMessageToCaller(string user, string message)
        => await Clients.Caller.ReceiveMessage(user, message);

    public async Task SendMessageToGroup(string user, string message)
        => await Clients.Group("SignalR Users").ReceiveMessage(user, message);
}

kullanarak Hub<IChatClient> istemci yöntemlerinin derleme zamanı denetimini etkinleştirir. Bu, Hub<T> yalnızca arabirimde tanımlanan yöntemlere erişim sağlayabildiği için dizelerin kullanılmasından kaynaklanan sorunları önler. Kesin olarak yazılan Hub<T> bir kullanmak, özelliğini kullanma SendAsyncözelliğini devre dışı bırakır.

Not

Sonek Async , yöntem adlarından çıkarılmamış. ile .on('MyMethodAsync')bir istemci yöntemi tanımlanmadığı sürece, ad olarak kullanmayın MyMethodAsync .

İstemci sonuçları

sunucu, istemcilere çağrı yapmaya ek olarak bir istemciden sonuç isteyebilir. Bunun için sunucunun kullanması ISingleClientProxy.InvokeAsync ve istemcinin işleyicisinden bir sonuç döndürmesi .On gerekir.

API'yi sunucuda kullanmanın iki yolu vardır; birincisi hub yönteminde veya Caller özelliğinde Clients çağırmaktırClient(...):

public class ChatHub : Hub
{
    public async Task<string> WaitForMessage(string connectionId)
    {
        var message = await Clients.Client(connectionId).InvokeAsync<string>(
            "GetMessage");
        return message;
    }
}

İkinci yol, örneğinde çağrısı Client(...) yapmaktır IHubContext<T>:

async Task SomeMethod(IHubContext<MyHub> context)
{
    string result = await context.Clients.Client(connectionID).InvokeAsync<string>(
        "GetMessage");
}

Kesin türe sahip hub'lar, arabirim yöntemlerinden de değer döndürebilir:

public interface IClient
{
    Task<string> GetMessage();
}

public class ChatHub : Hub<IClient>
{
    public async Task<string> WaitForMessage(string connectionId)
    {
        string message = await Clients.Client(connectionId).GetMessage();
        return message;
    }
}

İstemciler aşağıda gösterildiği gibi sonuçları işleyicilerinde .On(...) döndürür:

.NET istemcisi

hubConnection.On("GetMessage", async () =>
{
    Console.WriteLine("Enter message:");
    var message = await Console.In.ReadLineAsync();
    return message;
});

Typescript istemcisi

hubConnection.on("GetMessage", async () => {
    let promise = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("message");
        }, 100);
    });
    return promise;
});

Java istemcisi

hubConnection.onWithResult("GetMessage", () -> {
    return Single.just("message");
});

Hub yönteminin adını değiştirme

Varsayılan olarak, sunucu hub'ı yöntemi adı .NET yönteminin adıdır. Belirli bir yöntemin bu varsayılan davranışını değiştirmek için HubMethodName özniteliğini kullanın. İstemci, yöntemini çağırırken .NET yöntemi adı yerine bu adı kullanmalıdır:

[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
    => await Clients.User(user).SendAsync("ReceiveMessage", user, message);

Hub'a hizmet ekleme

Hub oluşturucuları, DI'den gelen hizmetleri parametre olarak kabul edebilir ve bu hizmetler bir hub yönteminde kullanılmak üzere sınıfındaki özelliklerde depolanabilir.

Farklı hub yöntemleri için veya kod yazmanın alternatif bir yolu olarak birden çok hizmet eklerken, hub yöntemleri DI'den gelen hizmetleri de kabul edebilir. Varsayılan olarak, hub yöntemi parametreleri mümkünse DI'den incelenir ve çözümlenir.

services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();

// ...

public class ChatHub : Hub
{
    public Task SendMessage(string user, string message, IDatabaseService dbService)
    {
        var userName = dbService.GetUserName(user);
        return Clients.All.SendAsync("ReceiveMessage", userName, message);
    }
}

Hizmetlerden gelen parametrelerin örtük çözümlemesi istenmiyorsa DisableImplicitFromServicesParameters ile devre dışı bırakın. Hub'da DI yöntemlerinden hangi parametrelerin çözümleneceğini açıkça belirtmek için seçeneğini kullanın DisableImplicitFromServicesParameters ve özniteliğini veya DI'den çözümlenmesi gereken hub yöntemi parametrelerinde uygulayan IFromServiceMetadata özel bir özniteliği kullanın[FromServices].

services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();
services.AddSignalR(options =>
{
    options.DisableImplicitFromServicesParameters = true;
});

// ...

public class ChatHub : Hub
{
    public Task SendMessage(string user, string message,
        [FromServices] IDatabaseService dbService)
    {
        var userName = dbService.GetUserName(user);
        return Clients.All.SendAsync("ReceiveMessage", userName, message);
    }
}

Not

Bu özellik, isteğe bağlı olarak DI uygulamaları tarafından uygulanan öğesini kullanır IServiceProviderIsService. Uygulamanın DI kapsayıcısı bu özelliği desteklemiyorsa, hub yöntemlerine hizmet ekleme desteklenmez.

Bağlantı için olayları işleme

Hubs API'sinde SignalR OnConnectedAsync bağlantıları yönetmek ve izlemek için ve OnDisconnectedAsync sanal yöntemleri sağlanır. bir istemci hub'a OnConnectedAsync bağlandığında eylemleri gerçekleştirmek için sanal yöntemi geçersiz kılın; örneğin, bunu bir gruba ekleyin:

public override async Task OnConnectedAsync()
{
    await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
    await base.OnConnectedAsync();
}

İstemci bağlantısı OnDisconnectedAsync kesildiğinde eylem gerçekleştirmek için sanal yöntemi geçersiz kılın. İstemcinin bağlantısı kasıtlı olarak, örneğin çağrısıyla connection.stop()exception kesilirse, parametresi olarak nullayarlanır. Ancak, ağ hatası gibi bir hata nedeniyle istemcinin bağlantısı kesilirse, exception parametre hatayı açıklayan bir özel durum içerir:

public override async Task OnDisconnectedAsync(Exception? exception)
{
    await base.OnDisconnectedAsync(exception);
}

RemoveFromGroupAsync içinde OnDisconnectedAsyncçağrılması gerekmez. Sizin için otomatik olarak işlenir.

Hataları işleme

Hub yöntemlerinde oluşan özel durumlar, yöntemini çağıran istemciye gönderilir. JavaScript istemcisinde invoke yöntemi bir JavaScript Promisedöndürür. İstemciler döndürülen söze bir catch işleyici ekleyebilir veya özel durumları işlemek için ile/asyncawait kullanabilir:try/catch

try {
  await connection.invoke("SendMessage", user, message);
} catch (err) {
  console.error(err);
}

Bir hub özel durum oluştururken bağlantılar kapatılamaz. Varsayılan olarak, SignalR aşağıdaki örnekte gösterildiği gibi istemciye genel bir hata iletisi döndürür:

Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.

Beklenmeyen özel durumlar genellikle veritabanı bağlantısı başarısız olduğunda tetiklenen bir özel durumdaki veritabanı sunucusunun adı gibi hassas bilgiler içerir. SignalR güvenlik önlemi olarak bu ayrıntılı hata iletilerini varsayılan olarak kullanıma sunmaz. Özel durum ayrıntılarının neden gizlendiğini öğrenmek için bkz . ASP.NET Core'da SignalRgüvenlikle ilgili dikkat edilmesi gerekenler.

İstemciye olağanüstü bir koşul yayılması gerekiyorsa sınıfını HubException kullanın. HubException bir hub yönteminde oluşturulursa, SignalRözel durum iletisinin tamamını değiştirilmemiş olarak istemciye gönderir:

public Task ThrowException()
    => throw new HubException("This error will be sent to the client!");

Not

SignalR yalnızca özel durumun özelliğini istemciye gönderir Message . Özel durumdaki yığın izlemesi ve diğer özellikler istemci tarafından kullanılamaz.

Ek kaynaklar

Tarafından Rachel Appel ve Kevin Griffin

Hubs API'si SignalR , bağlı istemcilerin sunucudaki yöntemleri çağırarak gerçek zamanlı iletişimi kolaylaştırmalarına olanak tanır. Sunucu, istemci tarafından çağrılan yöntemleri, istemci ise sunucu tarafından çağrılan yöntemleri tanımlar. SignalR ayrıca, her zaman Hub tarafından aracılık edilen dolaylı istemciden istemciye iletişimi etkinleştirir ve iletilerin SignalR tek tek istemciler, gruplar veya tüm bağlı istemcilere gönderilmesine olanak tanır. SignalR gerçek zamanlı istemciden sunucuya ve sunucudan istemciye iletişimi mümkün kılmak için gereken her şeyi gerçekleştirir.

Hub'ları yapılandırma SignalR

Hub'lar AddSignalR için SignalR gereken hizmetleri kaydetmek için çağrısında:Program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddSignalR();

Uç noktaları yapılandırmak SignalR için içinde de öğesini çağırabilirsinizProgram.csMapHub:

app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");

app.Run();

Not

ASP.NET Core SignalR sunucu tarafı derlemeleri artık .NET Core SDK ile yüklenir. Daha fazla bilgi için bkz SignalR . Paylaşılan çerçevedeki derlemeler.

Hub oluşturma ve kullanma

öğesinden Hubdevralan bir sınıf bildirerek bir hub oluşturun. İstemcilerden çağrılabilen hale getirmek için sınıfına yöntemler ekleyin public :

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
        => await Clients.All.SendAsync("ReceiveMessage", user, message);
}

Not

Hub'lar geçicidir:

  • Durumu hub sınıfının bir özelliğinde depolamayın. Her hub yöntemi çağrısı yeni bir hub örneğinde yürütülür.
  • Bağımlılık ekleme yoluyla doğrudan hub örneği oluşturmayın. Uygulamanızın başka bir yerinden bir istemciye ileti göndermek için kullanın IHubContext.
  • Hub'ın hayatta kalmasına bağlı zaman uyumsuz yöntemleri çağırırken kullanın await . Örneğin, gibi Clients.All.SendAsync(...) bir yöntem olmadan await çağrılırsa ve hub yöntemi tamamlanmadan önce SendAsync tamamlanırsa başarısız olabilir.

Context nesnesi

sınıfı, Hub bağlantı hakkında bilgi içeren aşağıdaki özellikleri içeren bir Context özellik içerir:

Özellik Açıklama
ConnectionId Bağlantının tarafından SignalRatanan benzersiz kimliğini alır. Her bağlantı için bir bağlantı kimliği vardır.
UserIdentifier Kullanıcı tanımlayıcısını alır. Varsayılan olarak, SignalR kullanıcı tanımlayıcısı olarak bağlantıyla ilişkilendirilmiş olan öğesini ClaimsPrincipal kullanırClaimTypes.NameIdentifier.
User ClaimsPrincipal Geçerli kullanıcıyla ilişkili olan öğesini alır.
Items Bu bağlantı kapsamında veri paylaşmak için kullanılabilecek bir anahtar/değer koleksiyonu alır. Veriler bu koleksiyonda depolanabilir ve farklı hub yöntemi çağrıları arasında bağlantı için kalıcı olur.
Features Bağlantıda kullanılabilen özellik koleksiyonunu alır. Şimdilik bu koleksiyon çoğu senaryoda gerekli olmadığından henüz ayrıntılı olarak belgelenmemiştir.
ConnectionAborted Bağlantı durdurulduğunda bunu bildiren bir CancellationToken alır.

Hub.Context ayrıca aşağıdaki yöntemleri içerir:

Metot Açıklama
GetHttpContext HttpContext Bağlantının veya bağlantının null bir HTTP isteğiyle ilişkilendirilip ilişkilendirnmediğini döndürür. HTTP bağlantıları için, HTTP üst bilgileri ve sorgu dizeleri gibi bilgileri almak için bu yöntemi kullanın.
Abort Bağlantıyı durdurur.

İstemciler nesnesi

sınıfı, Hub sunucu ve istemci arasındaki iletişim için aşağıdaki özellikleri içeren bir Clients özellik içerir:

Özellik Açıklama
All Tüm bağlı istemcilerde bir yöntemi çağırır
Caller İstemcide hub yöntemini çağıran bir yöntemi çağırır
Others Yöntemini çağıran istemci dışındaki tüm bağlı istemcilerde bir yöntemi çağırır

Hub.Clients ayrıca aşağıdaki yöntemleri içerir:

Metot Açıklama
AllExcept Belirtilen bağlantılar dışında tüm bağlı istemcilerde bir yöntemi çağırır
Client Belirli bir bağlı istemcide bir yöntemi çağırır
Clients Belirli bağlı istemcilerde bir yöntemi çağırır
Group Belirtilen gruptaki tüm bağlantılarda bir yöntemi çağırır
GroupExcept Belirtilen bağlantılar dışında belirtilen gruptaki tüm bağlantılarda bir yöntemi çağırır
Groups Birden çok bağlantı grubunda bir yöntemi çağırır
OthersInGroup Hub yöntemini çağıran istemci hariç olmak üzere bir bağlantı grubundaki bir yöntemi çağırır
User Belirli bir kullanıcıyla ilişkili tüm bağlantılarda bir yöntemi çağırır
Users Belirtilen kullanıcılarla ilişkili tüm bağlantılarda bir yöntemi çağırır

Yukarıdaki tablolardaki her özellik veya yöntem, yöntemi olan bir SendAsync nesne döndürür. yöntemi, SendAsync çağrılacak istemci yönteminin adını ve tüm parametreleri alır.

İstemcilere ileti gönderme

Belirli istemcilere çağrı yapmak için nesnesinin Clients özelliklerini kullanın. Aşağıdaki örnekte üç hub yöntemi vardır:

  • SendMessage kullanarak Clients.Alltüm bağlı istemcilere bir ileti gönderir.
  • SendMessageToCaller kullanarak Clients.Callerçağırana bir ileti gönderir.
  • SendMessageToGroup gruptaki SignalR Users tüm istemcilere bir ileti gönderir.
public async Task SendMessage(string user, string message)
    => await Clients.All.SendAsync("ReceiveMessage", user, message);

public async Task SendMessageToCaller(string user, string message)
    => await Clients.Caller.SendAsync("ReceiveMessage", user, message);

public async Task SendMessageToGroup(string user, string message)
    => await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);

Kesin türemiş hub'lar

kullanmanın SendAsync bir dezavantajı, çağrılacak istemci yöntemini belirtmek için bir dizeye bağlı olmasıdır. Bu, yöntem adı yanlış yazılmışsa veya istemcide eksikse kodu çalışma zamanı hatalarına açık bırakır.

kullanmanın SendAsync bir alternatifi, sınıfını Hub ile Hub<T>güçlü bir şekilde yazmaktır. Aşağıdaki örnekte, ChatHub istemci yöntemi adlı IChatClientbir arabirimde ayıklanmıştır:

public interface IChatClient
{
    Task ReceiveMessage(string user, string message);
}

Bu arabirim, önceki ChatHub örneği kesin olarak yazılacak şekilde yeniden düzenleme amacıyla kullanılabilir:

public class StronglyTypedChatHub : Hub<IChatClient>
{
    public async Task SendMessage(string user, string message)
        => await Clients.All.ReceiveMessage(user, message);

    public async Task SendMessageToCaller(string user, string message)
        => await Clients.Caller.ReceiveMessage(user, message);

    public async Task SendMessageToGroup(string user, string message)
        => await Clients.Group("SignalR Users").ReceiveMessage(user, message);
}

kullanarak Hub<IChatClient> istemci yöntemlerinin derleme zamanı denetimini etkinleştirir. Bu, Hub<T> yalnızca arabirimde tanımlanan yöntemlere erişim sağlayabildiği için dizelerin kullanılmasından kaynaklanan sorunları önler. Kesin olarak yazılan Hub<T> bir kullanmak, özelliğini kullanma SendAsyncözelliğini devre dışı bırakır.

Not

Sonek Async , yöntem adlarından çıkarılmamış. ile .on('MyMethodAsync')bir istemci yöntemi tanımlanmadığı sürece, ad olarak kullanmayın MyMethodAsync .

Hub yönteminin adını değiştirme

Varsayılan olarak, sunucu hub'ı yöntemi adı .NET yönteminin adıdır. Belirli bir yöntemin bu varsayılan davranışını değiştirmek için HubMethodName özniteliğini kullanın. İstemci, yöntemini çağırırken .NET yöntemi adı yerine bu adı kullanmalıdır:

[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
    => await Clients.User(user).SendAsync("ReceiveMessage", user, message);

Bağlantı için olayları işleme

Hubs API'sinde SignalR OnConnectedAsync bağlantıları yönetmek ve izlemek için ve OnDisconnectedAsync sanal yöntemleri sağlanır. bir istemci hub'a OnConnectedAsync bağlandığında eylemleri gerçekleştirmek için sanal yöntemi geçersiz kılın; örneğin, bunu bir gruba ekleyin:

public override async Task OnConnectedAsync()
{
    await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
    await base.OnConnectedAsync();
}

İstemci bağlantısı OnDisconnectedAsync kesildiğinde eylem gerçekleştirmek için sanal yöntemi geçersiz kılın. İstemcinin bağlantısı kasıtlı olarak, örneğin çağrısıyla connection.stop()exception kesilirse, parametresi olarak nullayarlanır. Ancak, ağ hatası gibi bir hata nedeniyle istemcinin bağlantısı kesilirse, exception parametre hatayı açıklayan bir özel durum içerir:

public override async Task OnDisconnectedAsync(Exception? exception)
{
    await base.OnDisconnectedAsync(exception);
}

RemoveFromGroupAsync içinde OnDisconnectedAsyncçağrılması gerekmez. Sizin için otomatik olarak işlenir.

Hataları işleme

Hub yöntemlerinde oluşan özel durumlar, yöntemini çağıran istemciye gönderilir. JavaScript istemcisinde invoke yöntemi bir JavaScript Promisedöndürür. İstemciler döndürülen söze bir catch işleyici ekleyebilir veya özel durumları işlemek için ile/asyncawait kullanabilir:try/catch

try {
  await connection.invoke("SendMessage", user, message);
} catch (err) {
  console.error(err);
}

Bir hub özel durum oluştururken bağlantılar kapatılamaz. Varsayılan olarak, SignalR aşağıdaki örnekte gösterildiği gibi istemciye genel bir hata iletisi döndürür:

Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.

Beklenmeyen özel durumlar genellikle veritabanı bağlantısı başarısız olduğunda tetiklenen bir özel durumdaki veritabanı sunucusunun adı gibi hassas bilgiler içerir. SignalR güvenlik önlemi olarak bu ayrıntılı hata iletilerini varsayılan olarak kullanıma sunmaz. Özel durum ayrıntılarının neden gizlendiğini öğrenmek için bkz . ASP.NET Core'da SignalRgüvenlikle ilgili dikkat edilmesi gerekenler.

İstemciye olağanüstü bir koşul yayılması gerekiyorsa sınıfını HubException kullanın. HubException bir hub yönteminde oluşturulursa, SignalRözel durum iletisinin tamamını değiştirilmemiş olarak istemciye gönderir:

public Task ThrowException()
    => throw new HubException("This error will be sent to the client!");

Not

SignalR yalnızca özel durumun özelliğini istemciye gönderir Message . Özel durumdaki yığın izlemesi ve diğer özellikler istemci tarafından kullanılamaz.

Ek kaynaklar

Tarafından Rachel Appel ve Kevin Griffin

Örnek kodu görüntüleme veya indirme (indirme)

Hub nedir?SignalR

Hubs API'si SignalR , bağlı istemcilerin sunucudaki yöntemleri çağırarak gerçek zamanlı iletişimi kolaylaştırmalarına olanak tanır. Sunucu, istemci tarafından çağrılan yöntemleri, istemci ise sunucu tarafından çağrılan yöntemleri tanımlar. SignalR ayrıca, her zaman Hub tarafından aracılık edilen dolaylı istemciden istemciye iletişimi etkinleştirir ve iletilerin SignalR tek tek istemciler, gruplar veya tüm bağlı istemcilere gönderilmesine olanak tanır. SignalR gerçek zamanlı istemciden sunucuya ve sunucudan istemciye iletişimi mümkün kılmak için gereken her şeyi gerçekleştirir.

Hub'ları yapılandırma SignalR

Ara SignalR yazılım, çağrılarak AddSignalRyapılandırılan bazı hizmetler gerektirir:

services.AddSignalR();

bir ASP.NET Core uygulamasına işlevsellik eklerkenSignalR, yöntemin UseEndpoints geri çağırmasını Startup.Configure çağırarak MapHub yolları ayarlayınSignalR:

app.UseRouting();
app.UseEndpoints(endpoints =>
{
    endpoints.MapHub<ChatHub>("/chathub");
});

Not

ASP.NET Core SignalR sunucu tarafı derlemeleri artık .NET Core SDK ile yüklenir. Daha fazla bilgi için bkz SignalR . Paylaşılan çerçevedeki derlemeler.

Hub oluşturma ve kullanma

öğesinden Hubdevralan bir sınıf bildirerek bir hub oluşturun ve genel yöntemler ekleyin. İstemciler olarak publictanımlanan yöntemleri çağırabilir:

public class ChatHub : Hub
{
    public Task SendMessage(string user, string message)
    {
        return Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

Herhangi bir C# yönteminde olduğu gibi, karmaşık türler ve diziler de dahil olmak üzere bir dönüş türü ve parametreleri belirtebilirsiniz. SignalR parametrelerinizdeki karmaşık nesnelerin ve dizilerin seri hale getirilmesini ve seri durumdan çıkarılıp döndürülme değerlerini işler.

Not

Hub'lar geçicidir:

  • Durumu hub sınıfındaki bir özellikte depolamayın. Her hub yöntemi çağrısı yeni bir hub örneğinde yürütülür.
  • Bağımlılık ekleme yoluyla doğrudan hub örneği oluşturmayın. Uygulamanızın başka bir yerinden bir istemciye ileti göndermek için kullanın IHubContext.
  • Hub'ın hayatta kalmasına bağlı zaman uyumsuz yöntemleri çağırırken kullanın await . Örneğin, gibi Clients.All.SendAsync(...) bir yöntem olmadan await çağrılırsa ve hub yöntemi tamamlanmadan önce SendAsync tamamlanırsa başarısız olabilir.

Context nesnesi

sınıfı, Hub bağlantı hakkında bilgi içeren aşağıdaki özellikleri içeren bir Context özelliğe sahiptir:

Özellik Açıklama
ConnectionId Bağlantının tarafından SignalRatanan benzersiz kimliğini alır. Her bağlantı için bir bağlantı kimliği vardır.
UserIdentifier Kullanıcı tanımlayıcısını alır. Varsayılan olarak, SignalR kullanıcı tanımlayıcısı olarak bağlantıyla ilişkilendirilmiş olan öğesini ClaimsPrincipal kullanırClaimTypes.NameIdentifier.
User ClaimsPrincipal Geçerli kullanıcıyla ilişkili olan öğesini alır.
Items Bu bağlantı kapsamında veri paylaşmak için kullanılabilecek bir anahtar/değer koleksiyonu alır. Veriler bu koleksiyonda depolanabilir ve farklı hub yöntemi çağrıları arasında bağlantı için kalıcı olur.
Features Bağlantıda kullanılabilen özellik koleksiyonunu alır. Şimdilik bu koleksiyon çoğu senaryoda gerekli olmadığından henüz ayrıntılı olarak belgelenmemiştir.
ConnectionAborted Bağlantı durdurulduğunda bunu bildiren bir CancellationToken alır.

Hub.Context ayrıca aşağıdaki yöntemleri içerir:

Metot Açıklama
GetHttpContext HttpContext Bağlantının veya bağlantının null bir HTTP isteğiyle ilişkilendirilip ilişkilendirnmediğini döndürür. HTTP bağlantıları için, HTTP üst bilgileri ve sorgu dizeleri gibi bilgileri almak için bu yöntemi kullanabilirsiniz.
Abort Bağlantıyı durdurur.

İstemciler nesnesi

sınıfı, Hub sunucu ve istemci arasındaki iletişim için aşağıdaki özellikleri içeren bir Clients özelliğe sahiptir:

Özellik Açıklama
All Tüm bağlı istemcilerde bir yöntemi çağırır
Caller İstemcide hub yöntemini çağıran bir yöntemi çağırır
Others Yöntemini çağıran istemci dışındaki tüm bağlı istemcilerde bir yöntemi çağırır

Hub.Clients ayrıca aşağıdaki yöntemleri içerir:

Metot Açıklama
AllExcept Belirtilen bağlantılar dışında tüm bağlı istemcilerde bir yöntemi çağırır
Client Belirli bir bağlı istemcide bir yöntemi çağırır
Clients Belirli bağlı istemcilerde bir yöntemi çağırır
Group Belirtilen gruptaki tüm bağlantılarda bir yöntemi çağırır
GroupExcept Belirtilen bağlantılar dışında belirtilen gruptaki tüm bağlantılarda bir yöntemi çağırır
Groups Birden çok bağlantı grubunda bir yöntemi çağırır
OthersInGroup Hub yöntemini çağıran istemci hariç olmak üzere bir bağlantı grubundaki bir yöntemi çağırır
User Belirli bir kullanıcıyla ilişkili tüm bağlantılarda bir yöntemi çağırır
Users Belirtilen kullanıcılarla ilişkili tüm bağlantılarda bir yöntemi çağırır

Yukarıdaki tablolardaki her özellik veya yöntem, yöntemi olan bir SendAsync nesne döndürür. yöntemi, SendAsync çağrılacak istemci yönteminin adını ve parametrelerini sağlamanıza olanak tanır.

İstemcilere ileti gönderme

Belirli istemcilere çağrı yapmak için nesnesinin Clients özelliklerini kullanın. Aşağıdaki örnekte üç Hub yöntemi vardır:

  • SendMessage kullanarak Clients.Alltüm bağlı istemcilere bir ileti gönderir.
  • SendMessageToCaller kullanarak Clients.Callerçağırana bir ileti gönderir.
  • SendMessageToGroup gruptaki SignalR Users tüm istemcilere bir ileti gönderir.
public Task SendMessage(string user, string message)
{
    return Clients.All.SendAsync("ReceiveMessage", user, message);
}

public Task SendMessageToCaller(string user, string message)
{
    return Clients.Caller.SendAsync("ReceiveMessage", user, message);
}

public Task SendMessageToGroup(string user, string message)
{
    return Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);
}

Kesin türemiş hub'lar

kullanmanın SendAsync bir dezavantajı, çağrılacak istemci yöntemini belirtmek için sihirli bir dizeye bağlı olmasıdır. Bu, yöntem adı yanlış yazılmışsa veya istemcide eksikse kodu çalışma zamanı hatalarına açık bırakır.

kullanmanın SendAsync bir alternatifi, ile Hub<T>kesin olarak yazmaktırHub. Aşağıdaki örnekte, ChatHub istemci yöntemleri adlı IChatClientbir arabirime ayıklanmıştır.

public interface IChatClient
{
    Task ReceiveMessage(string user, string message);
}

Bu arabirim, önceki ChatHub örneği yeniden düzenlemek için kullanılabilir:

    public class StronglyTypedChatHub : Hub<IChatClient>
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.ReceiveMessage(user, message);
        }

        public Task SendMessageToCaller(string user, string message)
        {
            return Clients.Caller.ReceiveMessage(user, message);
        }
}

kullanarak Hub<IChatClient> istemci yöntemlerinin derleme zamanı denetimini etkinleştirir. Bu, Hub<T> yalnızca arabirimde tanımlanan yöntemlere erişim sağlayabildiği için sihirli dizelerin kullanılmasından kaynaklanan sorunları önler.

Kesin olarak yazılan Hub<T> bir kullanmak, özelliğini kullanma SendAsyncözelliğini devre dışı bırakır. Arabirimde tanımlanan tüm yöntemler yine de zaman uyumsuz olarak tanımlanabilir. Aslında, bu yöntemlerin her biri bir Taskdöndürmelidir. Bu bir arabirim olduğundan anahtar sözcüğünü async kullanmayın. Örneğin:

public interface IClient
{
    Task ClientMethod();
}

Not

Sonek Async yöntem adından çıkarılmamış. İstemci yönteminiz ile .on('MyMethodAsync')tanımlanmadığı sürece, ad olarak kullanmamalısınız MyMethodAsync .

Hub yönteminin adını değiştirme

Varsayılan olarak, sunucu hub'ı yöntemi adı .NET yönteminin adıdır. Ancak, bu varsayılanı değiştirmek ve yöntem için el ile bir ad belirtmek için HubMethodName özniteliğini kullanabilirsiniz. İstemci, yöntemini çağırırken .NET yöntemi adı yerine bu adı kullanmalıdır:

[HubMethodName("SendMessageToUser")]
public Task DirectMessage(string user, string message)
{
    return Clients.User(user).SendAsync("ReceiveMessage", user, message);
}

Bağlantı için olayları işleme

Hubs API'sinde SignalR OnConnectedAsync bağlantıları yönetmek ve izlemek için ve OnDisconnectedAsync sanal yöntemleri sağlanır. İstemci Hub'a OnConnectedAsync bağlandığında eylemleri gerçekleştirmek için sanal yöntemi geçersiz kılın; örneğin, bunu bir gruba ekleyin:

public override async Task OnConnectedAsync()
{
    await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
    await base.OnConnectedAsync();
}

İstemci bağlantısı OnDisconnectedAsync kesildiğinde eylem gerçekleştirmek için sanal yöntemi geçersiz kılın. İstemcinin bağlantısı kasıtlı olarak kesilirse (örneğin çağrısı connection.stop()yaparak), exception parametresi olur null. Ancak, istemcinin bağlantısı bir hata (ağ hatası gibi) exception nedeniyle kesilirse, parametre hatayı açıklayan bir özel durum içerir:

public override async Task OnDisconnectedAsync(Exception exception)
{
    await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", "I", "disconnect");
    await base.OnDisconnectedAsync(exception);
}

RemoveFromGroupAsync içinde OnDisconnectedAsyncçağrılması gerekmez. Sizin için otomatik olarak işlenir.

Uyarı

Güvenlik uyarısı: ConnectionId Sunucu veya istemci sürümü Core 2.2 veya önceki bir sürüm ASP.NET kötü amaçlı kimliğe bürünmeye SignalR neden olabilir.

Hataları işleme

Hub yöntemlerinizde oluşan özel durumlar, yöntemini çağıran istemciye gönderilir. JavaScript istemcisinde invoke yöntemi bir JavaScript Promisedöndürür. İstemci kullanarak catchpromise'e bağlı bir işleyiciyle hata aldığında çağrılır ve JavaScript Error nesnesi olarak geçirilir:

connection.invoke("SendMessage", user, message).catch(err => console.error(err));

Hub'ınız özel durum oluşturursa bağlantılar kapatılamaz. Varsayılan olarak, SignalR istemciye genel bir hata iletisi döndürür. Örneğin:

Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'MethodName' on the server.

Beklenmeyen özel durumlar genellikle veritabanı bağlantısı başarısız olduğunda tetiklenen bir özel durumdaki veritabanı sunucusunun adı gibi hassas bilgiler içerir. SignalR güvenlik önlemi olarak bu ayrıntılı hata iletilerini varsayılan olarak kullanıma sunmaz. Özel durum ayrıntılarının neden gizlendiğini öğrenmek için bkz . ASP.NET Core'da SignalRgüvenlikle ilgili dikkat edilmesi gerekenler.

İstemciye yaymak istediğiniz olağanüstü bir durumunuz varsa sınıfını HubException kullanabilirsiniz. Hub yönteminizden bir HubException oluşturursanız, SignalR iletinin tamamı değiştirilmemiş olarak istemciye gönderilir:

public Task ThrowException()
{
    throw new HubException("This error will be sent to the client!");
}

Not

SignalR yalnızca özel durumun özelliğini istemciye gönderir Message . Özel durumdaki yığın izlemesi ve diğer özellikler istemci tarafından kullanılamaz.

Ek kaynaklar

Tarafından Rachel Appel ve Kevin Griffin

Örnek kodu görüntüleme veya indirme (indirme)

Hub nedir?SignalR

Hubs API'si SignalR , bağlı istemcilerin sunucudaki yöntemleri çağırarak gerçek zamanlı iletişimi kolaylaştırmalarına olanak tanır. Sunucu, istemci tarafından çağrılan yöntemleri, istemci ise sunucu tarafından çağrılan yöntemleri tanımlar. SignalR ayrıca, her zaman Hub tarafından aracılık edilen dolaylı istemciden istemciye iletişimi etkinleştirir ve iletilerin SignalR tek tek istemciler, gruplar veya tüm bağlı istemcilere gönderilmesine olanak tanır. SignalR gerçek zamanlı istemciden sunucuya ve sunucudan istemciye iletişimi mümkün kılmak için gereken her şeyi gerçekleştirir.

Hub'ları yapılandırma SignalR

Ara SignalR yazılım, çağrılarak AddSignalRyapılandırılan bazı hizmetler gerektirir:

services.AddSignalR();

bir ASP.NET Core uygulamasına işlevsellik eklerkenSignalR, yöntemini çağırarak UseSignalR Startup.Configure kurulum SignalR yolları:

app.UseSignalR(route =>
{
    route.MapHub<ChatHub>("/chathub");
});

Hub oluşturma ve kullanma

öğesinden Hubdevralan bir sınıf bildirerek bir hub oluşturun ve genel yöntemler ekleyin. İstemciler olarak publictanımlanan yöntemleri çağırabilir:

public class ChatHub : Hub
{
    public Task SendMessage(string user, string message)
    {
        return Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

Herhangi bir C# yönteminde olduğu gibi, karmaşık türler ve diziler de dahil olmak üzere bir dönüş türü ve parametreleri belirtebilirsiniz. SignalR parametrelerinizdeki karmaşık nesnelerin ve dizilerin seri hale getirilmesini ve seri durumdan çıkarılıp döndürülme değerlerini işler.

Not

Hub'lar geçicidir:

  • Durumu hub sınıfındaki bir özellikte depolamayın. Her hub yöntemi çağrısı yeni bir hub örneğinde yürütülür.
  • Bağımlılık ekleme yoluyla doğrudan hub örneği oluşturmayın. Uygulamanızın başka bir yerinden bir istemciye ileti göndermek için kullanın IHubContext.
  • Hub'ın hayatta kalmasına bağlı zaman uyumsuz yöntemleri çağırırken kullanın await . Örneğin, gibi Clients.All.SendAsync(...) bir yöntem olmadan await çağrılırsa ve hub yöntemi tamamlanmadan önce SendAsync tamamlanırsa başarısız olabilir.

Context nesnesi

sınıfı, Hub bağlantı hakkında bilgi içeren aşağıdaki özellikleri içeren bir Context özelliğe sahiptir:

Özellik Açıklama
ConnectionId Bağlantının tarafından SignalRatanan benzersiz kimliğini alır. Her bağlantı için bir bağlantı kimliği vardır.
UserIdentifier Kullanıcı tanımlayıcısını alır. Varsayılan olarak, SignalR kullanıcı tanımlayıcısı olarak bağlantıyla ilişkilendirilmiş olan öğesini ClaimsPrincipal kullanırClaimTypes.NameIdentifier.
User ClaimsPrincipal Geçerli kullanıcıyla ilişkili olan öğesini alır.
Items Bu bağlantı kapsamında veri paylaşmak için kullanılabilecek bir anahtar/değer koleksiyonu alır. Veriler bu koleksiyonda depolanabilir ve farklı hub yöntemi çağrıları arasında bağlantı için kalıcı olur.
Features Bağlantıda kullanılabilen özellik koleksiyonunu alır. Şimdilik bu koleksiyon çoğu senaryoda gerekli olmadığından henüz ayrıntılı olarak belgelenmemiştir.
ConnectionAborted Bağlantı durdurulduğunda bunu bildiren bir CancellationToken alır.

Hub.Context ayrıca aşağıdaki yöntemleri içerir:

Metot Açıklama
GetHttpContext HttpContext Bağlantının veya bağlantının null bir HTTP isteğiyle ilişkilendirilip ilişkilendirnmediğini döndürür. HTTP bağlantıları için, HTTP üst bilgileri ve sorgu dizeleri gibi bilgileri almak için bu yöntemi kullanabilirsiniz.
Abort Bağlantıyı durdurur.

İstemciler nesnesi

sınıfı, Hub sunucu ve istemci arasındaki iletişim için aşağıdaki özellikleri içeren bir Clients özelliğe sahiptir:

Özellik Açıklama
All Tüm bağlı istemcilerde bir yöntemi çağırır
Caller İstemcide hub yöntemini çağıran bir yöntemi çağırır
Others Yöntemini çağıran istemci dışındaki tüm bağlı istemcilerde bir yöntemi çağırır

Hub.Clients ayrıca aşağıdaki yöntemleri içerir:

Metot Açıklama
AllExcept Belirtilen bağlantılar dışında tüm bağlı istemcilerde bir yöntemi çağırır
Client Belirli bir bağlı istemcide bir yöntemi çağırır
Clients Belirli bağlı istemcilerde bir yöntemi çağırır
Group Belirtilen gruptaki tüm bağlantılarda bir yöntemi çağırır
GroupExcept Belirtilen bağlantılar dışında belirtilen gruptaki tüm bağlantılarda bir yöntemi çağırır
Groups Birden çok bağlantı grubunda bir yöntemi çağırır
OthersInGroup Hub yöntemini çağıran istemci hariç olmak üzere bir bağlantı grubundaki bir yöntemi çağırır
User Belirli bir kullanıcıyla ilişkili tüm bağlantılarda bir yöntemi çağırır
Users Belirtilen kullanıcılarla ilişkili tüm bağlantılarda bir yöntemi çağırır

Yukarıdaki tablolardaki her özellik veya yöntem, yöntemi olan bir SendAsync nesne döndürür. yöntemi, SendAsync çağrılacak istemci yönteminin adını ve parametrelerini sağlamanıza olanak tanır.

İstemcilere ileti gönderme

Belirli istemcilere çağrı yapmak için nesnesinin Clients özelliklerini kullanın. Aşağıdaki örnekte üç Hub yöntemi vardır:

  • SendMessage kullanarak Clients.Alltüm bağlı istemcilere bir ileti gönderir.
  • SendMessageToCaller kullanarak Clients.Callerçağırana bir ileti gönderir.
  • SendMessageToGroup gruptaki SignalR Users tüm istemcilere bir ileti gönderir.
public Task SendMessage(string user, string message)
{
    return Clients.All.SendAsync("ReceiveMessage", user, message);
}

public Task SendMessageToCaller(string user, string message)
{
    return Clients.Caller.SendAsync("ReceiveMessage", user, message);
}

public Task SendMessageToGroup(string user, string message)
{
    return Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);
}

Kesin türemiş hub'lar

kullanmanın SendAsync bir dezavantajı, çağrılacak istemci yöntemini belirtmek için sihirli bir dizeye bağlı olmasıdır. Bu, yöntem adı yanlış yazılmışsa veya istemcide eksikse kodu çalışma zamanı hatalarına açık bırakır.

kullanmanın SendAsync bir alternatifi, ile Hub<T>kesin olarak yazmaktırHub. Aşağıdaki örnekte, ChatHub istemci yöntemleri adlı IChatClientbir arabirime ayıklanmıştır.

public interface IChatClient
{
    Task ReceiveMessage(string user, string message);
}

Bu arabirim, önceki ChatHub örneği yeniden düzenlemek için kullanılabilir:

    public class StronglyTypedChatHub : Hub<IChatClient>
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.ReceiveMessage(user, message);
        }

        public Task SendMessageToCaller(string user, string message)
        {
            return Clients.Caller.ReceiveMessage(user, message);
        }
}

kullanarak Hub<IChatClient> istemci yöntemlerinin derleme zamanı denetimini etkinleştirir. Bu, Hub<T> yalnızca arabirimde tanımlanan yöntemlere erişim sağlayabildiği için sihirli dizelerin kullanılmasından kaynaklanan sorunları önler.

Kesin olarak yazılan Hub<T> bir kullanmak, özelliğini kullanma SendAsyncözelliğini devre dışı bırakır. Arabirimde tanımlanan tüm yöntemler yine de zaman uyumsuz olarak tanımlanabilir. Aslında, bu yöntemlerin her biri bir Taskdöndürmelidir. Bu bir arabirim olduğundan anahtar sözcüğünü async kullanmayın. Örneğin:

public interface IClient
{
    Task ClientMethod();
}

Not

Sonek Async yöntem adından çıkarılmamış. İstemci yönteminiz ile .on('MyMethodAsync')tanımlanmadığı sürece, ad olarak kullanmamalısınız MyMethodAsync .

Hub yönteminin adını değiştirme

Varsayılan olarak, sunucu hub'ı yöntemi adı .NET yönteminin adıdır. Ancak, bu varsayılanı değiştirmek ve yöntem için el ile bir ad belirtmek için HubMethodName özniteliğini kullanabilirsiniz. İstemci, yöntemini çağırırken .NET yöntemi adı yerine bu adı kullanmalıdır:

[HubMethodName("SendMessageToUser")]
public Task DirectMessage(string user, string message)
{
    return Clients.User(user).SendAsync("ReceiveMessage", user, message);
}

Bağlantı için olayları işleme

Hubs API'sinde SignalR OnConnectedAsync bağlantıları yönetmek ve izlemek için ve OnDisconnectedAsync sanal yöntemleri sağlanır. İstemci Hub'a OnConnectedAsync bağlandığında eylemleri gerçekleştirmek için sanal yöntemi geçersiz kılın; örneğin, bunu bir gruba ekleyin:

public override async Task OnConnectedAsync()
{
    await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
    await base.OnConnectedAsync();
}

İstemci bağlantısı OnDisconnectedAsync kesildiğinde eylem gerçekleştirmek için sanal yöntemi geçersiz kılın. İstemcinin bağlantısı kasıtlı olarak kesilirse (örneğin çağrısı connection.stop()yaparak), exception parametresi olur null. Ancak, istemcinin bağlantısı bir hata (ağ hatası gibi) exception nedeniyle kesilirse, parametre hatayı açıklayan bir özel durum içerir:

public override async Task OnDisconnectedAsync(Exception exception)
{
    await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", "I", "disconnect");
    await base.OnDisconnectedAsync(exception);
}

RemoveFromGroupAsync içinde OnDisconnectedAsyncçağrılması gerekmez. Sizin için otomatik olarak işlenir.

Uyarı

Güvenlik uyarısı: ConnectionId Sunucu veya istemci sürümü Core 2.2 veya önceki bir sürüm ASP.NET kötü amaçlı kimliğe bürünmeye SignalR neden olabilir.

Hataları işleme

Hub yöntemlerinizde oluşan özel durumlar, yöntemini çağıran istemciye gönderilir. JavaScript istemcisinde invoke yöntemi bir JavaScript Promisedöndürür. İstemci kullanarak catchpromise'e bağlı bir işleyiciyle hata aldığında çağrılır ve JavaScript Error nesnesi olarak geçirilir:

connection.invoke("SendMessage", user, message).catch(err => console.error(err));

Hub'ınız özel durum oluşturursa bağlantılar kapatılamaz. Varsayılan olarak, SignalR istemciye genel bir hata iletisi döndürür. Örneğin:

Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'MethodName' on the server.

Beklenmeyen özel durumlar genellikle veritabanı bağlantısı başarısız olduğunda tetiklenen bir özel durumdaki veritabanı sunucusunun adı gibi hassas bilgiler içerir. SignalR güvenlik önlemi olarak bu ayrıntılı hata iletilerini varsayılan olarak kullanıma sunmaz. Özel durum ayrıntılarının neden gizlendiğini öğrenmek için bkz . ASP.NET Core'da SignalRgüvenlikle ilgili dikkat edilmesi gerekenler.

İstemciye yaymak istediğiniz olağanüstü bir durumunuz varsa sınıfını HubException kullanabilirsiniz. Hub yönteminizden bir HubException oluşturursanız, SignalR iletinin tamamı değiştirilmemiş olarak istemciye gönderilir:

public Task ThrowException()
{
    throw new HubException("This error will be sent to the client!");
}

Not

SignalR yalnızca özel durumun özelliğini istemciye gönderir Message . Özel durumdaki yığın izlemesi ve diğer özellikler istemci tarafından kullanılamaz.

Ek kaynaklar