Aracılığıyla paylaş


ASP.NET Core için SignalR'de hub'ları 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ırın SignalR

Hub'ların SignalR için gereken hizmetleri kaydetmek amacıyla Program.cs'da AddSignalR çağrısını yapın.

var builder = WebApplication.CreateBuilder(args);

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

Uç noktaları yapılandırmak için SignalR öğesini ve aynı zamanda MapHub, Program.cs çağırın.

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

app.Run();

Note

ASP.NET Core SignalR sunucu tarafı derlemeleri artık .NET Core SDK ile yüklenir. Daha fazla bilgi için paylaşılan çerçevedeki derlemelere bakın.

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);
}

Note

Hub'lar geçicidir:

  • Hub sınıfının bir özelliğinde durumu 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 direkt bir hub örneği oluşturmayın. Uygulamanızın başka bir yerinden bir istemciye ileti göndermek için kullanın IHubContext.
  • Asenkron yöntemlerin hub'ın hayatta kalmasına bağlı olduğu durumlarda await kullanın. Örneğin, await olmadan Clients.All.SendAsync(...) gibi bir yöntem çağrıldığında ve SendAsync bitmeden önce hub yöntemi tamamlarsa başarısız olabilir.

Bir Context nesnesi

Hub sınıfı, bağlantı hakkında bilgi içeren ve aşağıdaki özellikleri barındıran bir Context özelliği içerir.

Property Description
ConnectionId Bağlantının SignalR tarafından atanan 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, bağlantıyla ilişkilendirilmiş ClaimsPrincipal'den ClaimTypes.NameIdentifier'i kullanıcı tanımlayıcısı olarak kullanır.
User Geçerli kullanıcıyla ilişkili olan ClaimsPrincipal öğ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ıdaki kullanılabilen özelliklerin 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:

Method Description
GetHttpContext HttpContext bağlantıyı döndürür veya bağlantı bir HTTP isteğiyle ilişkilendirilmemişse null 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ı iptal eder.

İstemci 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:

Property Description
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:

Method Description
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, bir SendAsync yöntemine sahip bir nesne döndürür. SendAsync yöntemi, çağrılacak olan istemci yönteminin adını ve herhangi bir parametreyi alır.

ve Client yöntemleri tarafından Caller döndürülen nesne, istemciden bir sonuç beklemek için kullanılabilecek bir InvokeAsyncyö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.

SendAsync kullanmak yerine, Hub sınıfını Hub<T> ile güçlü bir şekilde tip belirlemektir. Aşağıdaki örnekte, ChatHub istemci yöntemi, adlı IChatClient isimli bir arabirime çıkartılmış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 türde bir Hub<T> kullanmak, SendAsync işlevini devre dışı bırakır.

Note

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

İstemci sonuçları

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

API'yi sunucuda kullanmanın iki yolu vardır; birincisi, bir Hub yönteminde Clients özelliği üzerinden Client(...) veya Caller çağrısı yapmaktır.

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

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

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 .On(...) işleyicilerinde sonuçları geri 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 yöntemlerinde DI'den hangi parametrelerin çözüleceğini açıkça belirtmek için, DisableImplicitFromServicesParameters seçeneğini kullanın ve DI'den çözümlenmesi gereken hub yöntemi parametrelerinin parametrelerinde [FromServices] özniteliğini veya uygulayan özel bir öznitelik kullanın IFromServiceMetadata.

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);
    }
}

Note

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

Bağımlılık Enjeksiyonu'nda anahtarlı hizmetler desteği

Anahtarlı hizmetler , anahtarları kullanarak Bağımlılık Ekleme (DI) hizmetlerini kaydetmeye ve almaya yönelik bir mekanizmayı ifade eder. Bir hizmet, AddKeyedSingleton (veya AddKeyedScoped ya da AddKeyedTransient) çağrılarak bir anahtarla ilişkilendirilir. Özniteliği [FromKeyedServices] ile anahtarı belirterek kayıtlı bir hizmete erişin. 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ıdaki olayları yönet

Hubs API, SignalR ve OnConnectedAsync bağlantılarını yönetmek ve izlemek için OnDisconnectedAsync sanal yöntemlerini sağlar. 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ı kesildiğinde eylemleri gerçekleştirmek için OnDisconnectedAsync sanal yöntemi geçersiz kılın. İstemcinin bağlantısı kasıtlı olarak, örneğin connection.stop() çağrısı yoluyla kesilirse, exception parametresi null olarak ayarlanı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, OnDisconnectedAsync içinde çağrılmasına gerek yoktur, sizin yerinize otomatik olarak işlenir.

Hatalarla başa çıkma

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 ya da özel durumları işlemek için try/catch ile async/await kullanabilir.

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!");

Note

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ırın SignalR

Hub'ların SignalR için gereken hizmetleri kaydetmek amacıyla Program.cs'da AddSignalR çağrısını yapın.

var builder = WebApplication.CreateBuilder(args);

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

Uç noktaları yapılandırmak için SignalR öğesini ve aynı zamanda MapHub, Program.cs çağırın.

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

app.Run();

Note

ASP.NET Core SignalR sunucu tarafı derlemeleri artık .NET Core SDK ile yüklenir. Daha fazla bilgi için paylaşılan çerçevedeki derlemelere bakın.

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);
}

Note

Hub'lar geçicidir:

  • Hub sınıfının bir özelliğinde durumu 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 direkt bir hub örneği oluşturmayın. Uygulamanızın başka bir yerinden bir istemciye ileti göndermek için kullanın IHubContext.
  • Asenkron yöntemlerin hub'ın hayatta kalmasına bağlı olduğu durumlarda await kullanın. Örneğin, await olmadan Clients.All.SendAsync(...) gibi bir yöntem çağrıldığında ve SendAsync bitmeden önce hub yöntemi tamamlarsa başarısız olabilir.

Bir Context nesnesi

Hub sınıfı, bağlantı hakkında bilgi içeren ve aşağıdaki özellikleri barındıran bir Context özelliği içerir.

Property Description
ConnectionId Bağlantının SignalR tarafından atanan 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, bağlantıyla ilişkilendirilmiş ClaimsPrincipal'den ClaimTypes.NameIdentifier'i kullanıcı tanımlayıcısı olarak kullanır.
User Geçerli kullanıcıyla ilişkili olan ClaimsPrincipal öğ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ıdaki kullanılabilen özelliklerin 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:

Method Description
GetHttpContext HttpContext bağlantıyı döndürür veya bağlantı bir HTTP isteğiyle ilişkilendirilmemişse null 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ı iptal eder.

İstemci 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:

Property Description
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:

Method Description
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, bir SendAsync yöntemine sahip bir nesne döndürür. SendAsync yöntemi, çağrılacak olan istemci yönteminin adını ve herhangi bir parametreyi alır.

ve Client yöntemleri tarafından Caller döndürülen nesne, istemciden bir sonuç beklemek için kullanılabilecek bir InvokeAsyncyö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.

SendAsync kullanmak yerine, Hub sınıfını Hub<T> ile güçlü bir şekilde tip belirlemektir. Aşağıdaki örnekte, ChatHub istemci yöntemi, adlı IChatClient isimli bir arabirime çıkartılmış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 türde bir Hub<T> kullanmak, SendAsync işlevini devre dışı bırakır.

Note

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

İstemci sonuçları

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

API'yi sunucuda kullanmanın iki yolu vardır; birincisi, bir Hub yönteminde Clients özelliği üzerinden Client(...) veya Caller çağrısı yapmaktır.

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

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

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 .On(...) işleyicilerinde sonuçları geri 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 yöntemlerinde DI'den hangi parametrelerin çözüleceğini açıkça belirtmek için, DisableImplicitFromServicesParameters seçeneğini kullanın ve DI'den çözümlenmesi gereken hub yöntemi parametrelerinin parametrelerinde [FromServices] özniteliğini veya uygulayan özel bir öznitelik kullanın IFromServiceMetadata.

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);
    }
}

Note

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

Bağlantıdaki olayları yönet

Hubs API, SignalR ve OnConnectedAsync bağlantılarını yönetmek ve izlemek için OnDisconnectedAsync sanal yöntemlerini sağlar. 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ı kesildiğinde eylemleri gerçekleştirmek için OnDisconnectedAsync sanal yöntemi geçersiz kılın. İstemcinin bağlantısı kasıtlı olarak, örneğin connection.stop() çağrısı yoluyla kesilirse, exception parametresi null olarak ayarlanı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 OnDisconnectedAsync çağrılması gerekmez, sizin için otomatik olarak işlenir.

Hatalarla başa çıkma

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 ya da özel durumları işlemek için try/catch ile async/await kullanabilir.

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!");

Note

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ırın SignalR

Hub'ların SignalR için gereken hizmetleri kaydetmek amacıyla Program.cs'da AddSignalR çağrısını yapın.

var builder = WebApplication.CreateBuilder(args);

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

Uç noktaları yapılandırmak için SignalR öğesini ve aynı zamanda MapHub, Program.cs çağırın.

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

app.Run();

Note

ASP.NET Core SignalR sunucu tarafı derlemeleri artık .NET Core SDK ile yüklenir. Daha fazla bilgi için paylaşılan çerçevedeki derlemelere bakın.

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);
}

Note

Hub'lar geçicidir:

  • Hub sınıfının bir özelliğinde durumu 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 direkt bir hub örneği oluşturmayın. Uygulamanızın başka bir yerinden bir istemciye ileti göndermek için kullanın IHubContext.
  • Asenkron yöntemlerin hub'ın hayatta kalmasına bağlı olduğu durumlarda await kullanın. Örneğin, await olmadan Clients.All.SendAsync(...) gibi bir yöntem çağrıldığında ve SendAsync bitmeden önce hub yöntemi tamamlarsa başarısız olabilir.

Bir Context nesnesi

Hub sınıfı, bağlantı hakkında bilgi içeren ve aşağıdaki özellikleri barındıran bir Context özelliği içerir.

Property Description
ConnectionId Bağlantının SignalR tarafından atanan 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, bağlantıyla ilişkilendirilmiş ClaimsPrincipal'den ClaimTypes.NameIdentifier'i kullanıcı tanımlayıcısı olarak kullanır.
User Geçerli kullanıcıyla ilişkili olan ClaimsPrincipal öğ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ıdaki kullanılabilen özelliklerin 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:

Method Description
GetHttpContext HttpContext bağlantıyı döndürür veya bağlantı bir HTTP isteğiyle ilişkilendirilmemişse null 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ı iptal eder.

İstemci 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:

Property Description
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:

Method Description
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, bir SendAsync yöntemine sahip bir nesne döndürür. SendAsync yöntemi, çağrılacak olan istemci yönteminin adını ve herhangi bir parametreyi 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.

SendAsync kullanmak yerine, Hub sınıfını Hub<T> ile güçlü bir şekilde tip belirlemektir. Aşağıdaki örnekte, ChatHub istemci yöntemi, adlı IChatClient isimli bir arabirime çıkartılmış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 türde bir Hub<T> kullanmak, SendAsync işlevini devre dışı bırakır.

Note

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

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ıdaki olayları yönet

Hubs API, SignalR ve OnConnectedAsync bağlantılarını yönetmek ve izlemek için OnDisconnectedAsync sanal yöntemlerini sağlar. 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ı kesildiğinde eylemleri gerçekleştirmek için OnDisconnectedAsync sanal yöntemi geçersiz kılın. İstemcinin bağlantısı kasıtlı olarak, örneğin connection.stop() çağrısı yoluyla kesilirse, exception parametresi null olarak ayarlanı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 OnDisconnectedAsync çağrılması gerekmez, sizin için otomatik olarak işlenir.

Hatalarla başa çıkma

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 ya da özel durumları işlemek için try/catch ile async/await kullanabilir.

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!");

Note

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ırın SignalR

SignalR ara yazılım, AddSignalR çağrılarak yapılandırılan bazı hizmetleri gerektirir.

services.AddSignalR();

bir ASP.NET Core uygulamasına SignalR işlevselliğini eklerken, Startup.Configure yönteminin UseEndpoints geri çağırmasında MapHub çağırarak SignalR rotalarını ayarlayın.

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

Note

ASP.NET Core SignalR sunucu tarafı derlemeleri artık .NET Core SDK ile yüklenir. Daha fazla bilgi için paylaşılan çerçevedeki derlemelere bakın.

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 serileştirilmesini ve deserileştirilmesini yönetir.

Note

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 direkt bir hub örneği oluşturmayın. Uygulamanızın başka bir yerinden bir istemciye ileti göndermek için kullanın IHubContext.
  • Asenkron yöntemlerin hub'ın hayatta kalmasına bağlı olduğu durumlarda await kullanın. Örneğin, await olmadan Clients.All.SendAsync(...) gibi bir yöntem çağrıldığında ve SendAsync bitmeden önce hub yöntemi tamamlarsa başarısız olabilir.

Bir Context nesnesi

sınıfı, Context özelliği ile bağlantı hakkında bilgi veren aşağıdaki özelliklere sahiptir:

Property Description
ConnectionId Bağlantının SignalR tarafından atanan 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, bağlantıyla ilişkilendirilmiş ClaimsPrincipal'den ClaimTypes.NameIdentifier'i kullanıcı tanımlayıcısı olarak kullanır.
User Geçerli kullanıcıyla ilişkili olan ClaimsPrincipal öğ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ıdaki kullanılabilen özelliklerin 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:

Method Description
GetHttpContext HttpContext bağlantıyı döndürür veya bağlantı bir HTTP isteğiyle ilişkilendirilmemişse null 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ı iptal eder.

İstemci 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:

Property Description
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:

Method Description
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, bir SendAsync yöntemine sahip bir 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.

SendAsync kullanmaya bir alternatif, Hub'i Hub<T> ile kesin olarak yazmaktır. Aşağıdaki örnekte, ChatHub istemci yöntemleri IChatClient adlı bir arabirime taşınmış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 türde bir Hub<T> kullanmak, SendAsync işlevini 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();
}

Note

Sonek Async yöntem adından çıkartılmamış. İstemci yönteminiz .on('MyMethodAsync') olarak tanımlanmadıkça, MyMethodAsync ad olarak kullanmamalısınız.

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ıdaki olayları yönet

Hubs API, SignalR ve OnConnectedAsync bağlantılarını yönetmek ve izlemek için OnDisconnectedAsync sanal yöntemlerini sağlar. İ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ı kesildiğinde eylemleri gerçekleştirmek için OnDisconnectedAsync sanal yöntemi geçersiz kılın. İstemci bilerek bağlantıyı keserse (örneğin çağrı connection.stop() yaparak), exception parametresi null olur. 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 OnDisconnectedAsync çağrılması gerekmez, sizin için otomatik olarak işlenir.

Warning

Güvenlik uyarısı: ConnectionId ifşa edilirse, SignalR sunucu veya istemci sürümü ASP.NET Core 2.2 veya önceki sürümlerden biri olduğunda kötü amaçlı kimliğe bürünmeye neden olabilir.

Hatalarla başa çıkma

Hub yöntemlerinde oluşan istisnalar, yöntemi çağıran istemciye gönderilir. JavaScript istemcisinde invoke yöntemi bir JavaScript Promisedöndürür. İstemci, catch kullanarak promise'e bağlı bir işleyici ile bir hata aldığında, bu işleyici çağrılır ve bir JavaScript Error nesnesi olarak geçirilir.

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

Hub'ınız bir istisna fırlatırsa bağlantılar kapanmaz. 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 iletmek 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!");
}

Note

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ırın SignalR

SignalR ara yazılım, AddSignalR çağrılarak yapılandırılan bazı hizmetleri gerektirir.

services.AddSignalR();

ASP.NET Core uygulamasına SignalR işlevselliği eklerken, Startup.Configure yönteminde SignalRUseSignalR çağırarak yolları ayarlayın.

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 serileştirilmesini ve deserileştirilmesini yönetir.

Note

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 direkt bir hub örneği oluşturmayın. Uygulamanızın başka bir yerinden bir istemciye ileti göndermek için kullanın IHubContext.
  • Asenkron yöntemlerin hub'ın hayatta kalmasına bağlı olduğu durumlarda await kullanın. Örneğin, await olmadan Clients.All.SendAsync(...) gibi bir yöntem çağrıldığında ve SendAsync bitmeden önce hub yöntemi tamamlarsa başarısız olabilir.

Bir Context nesnesi

sınıfı, Context özelliği ile bağlantı hakkında bilgi veren aşağıdaki özelliklere sahiptir:

Property Description
ConnectionId Bağlantının SignalR tarafından atanan 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, bağlantıyla ilişkilendirilmiş ClaimsPrincipal'den ClaimTypes.NameIdentifier'i kullanıcı tanımlayıcısı olarak kullanır.
User Geçerli kullanıcıyla ilişkili olan ClaimsPrincipal öğ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ıdaki kullanılabilen özelliklerin 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:

Method Description
GetHttpContext HttpContext bağlantıyı döndürür veya bağlantı bir HTTP isteğiyle ilişkilendirilmemişse null 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ı iptal eder.

İstemci 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:

Property Description
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:

Method Description
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, bir SendAsync yöntemine sahip bir 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.

SendAsync kullanmaya bir alternatif, Hub'i Hub<T> ile kesin olarak yazmaktır. Aşağıdaki örnekte, ChatHub istemci yöntemleri IChatClient adlı bir arabirime taşınmış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 türde bir Hub<T> kullanmak, SendAsync işlevini 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();
}

Note

Sonek Async yöntem adından çıkartılmamış. İstemci yönteminiz .on('MyMethodAsync') olarak tanımlanmadıkça, MyMethodAsync ad olarak kullanmamalısınız.

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ıdaki olayları yönet

Hubs API, SignalR ve OnConnectedAsync bağlantılarını yönetmek ve izlemek için OnDisconnectedAsync sanal yöntemlerini sağlar. İ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ı kesildiğinde eylemleri gerçekleştirmek için OnDisconnectedAsync sanal yöntemi geçersiz kılın. İstemci bilerek bağlantıyı keserse (örneğin çağrı connection.stop() yaparak), exception parametresi null olur. 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 OnDisconnectedAsync çağrılması gerekmez, sizin için otomatik olarak işlenir.

Warning

Güvenlik uyarısı: ConnectionId ifşa edilirse, SignalR sunucu veya istemci sürümü ASP.NET Core 2.2 veya önceki sürümlerden biri olduğunda kötü amaçlı kimliğe bürünmeye neden olabilir.

Hatalarla başa çıkma

Hub yöntemlerinde oluşan istisnalar, yöntemi çağıran istemciye gönderilir. JavaScript istemcisinde invoke yöntemi bir JavaScript Promisedöndürür. İstemci, catch kullanarak promise'e bağlı bir işleyici ile bir hata aldığında, bu işleyici çağrılır ve bir JavaScript Error nesnesi olarak geçirilir.

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

Hub'ınız bir istisna fırlatırsa bağlantılar kapanmaz. 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 iletmek 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!");
}

Note

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