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.cs
MapHub:
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
- 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, gibiClients.All.SendAsync(...)
bir yöntem olmadanawait
çağrılırsa ve hub yöntemi tamamlanmadan önceSendAsync
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
kullanarakClients.All
tüm bağlı istemcilere bir ileti gönderir.SendMessageToCaller
kullanarakClients.Caller
çağırana bir ileti gönderir.SendMessageToGroup
gruptakiSignalR 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ı IChatClient
bir 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 null
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 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 Promise
döndürür. İstemciler döndürülen söze bir catch
işleyici ekleyebilir veya özel durumları işlemek için ile/async
await
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.cs
MapHub:
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
- 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, gibiClients.All.SendAsync(...)
bir yöntem olmadanawait
çağrılırsa ve hub yöntemi tamamlanmadan önceSendAsync
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
kullanarakClients.All
tüm bağlı istemcilere bir ileti gönderir.SendMessageToCaller
kullanarakClients.Caller
çağırana bir ileti gönderir.SendMessageToGroup
gruptakiSignalR 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ı IChatClient
bir 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 null
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 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 Promise
döndürür. İstemciler döndürülen söze bir catch
işleyici ekleyebilir veya özel durumları işlemek için ile/async
await
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.cs
MapHub:
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
- 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, gibiClients.All.SendAsync(...)
bir yöntem olmadanawait
çağrılırsa ve hub yöntemi tamamlanmadan önceSendAsync
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
kullanarakClients.All
tüm bağlı istemcilere bir ileti gönderir.SendMessageToCaller
kullanarakClients.Caller
çağırana bir ileti gönderir.SendMessageToGroup
gruptakiSignalR 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ı IChatClient
bir 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 null
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 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 Promise
döndürür. İstemciler döndürülen söze bir catch
işleyici ekleyebilir veya özel durumları işlemek için ile/async
await
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 public
tanı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, gibiClients.All.SendAsync(...)
bir yöntem olmadanawait
çağrılırsa ve hub yöntemi tamamlanmadan önceSendAsync
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
kullanarakClients.All
tüm bağlı istemcilere bir ileti gönderir.SendMessageToCaller
kullanarakClients.Caller
çağırana bir ileti gönderir.SendMessageToGroup
gruptakiSignalR 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ı IChatClient
bir 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 Task
dö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 Promise
döndürür. İstemci kullanarak catch
promise'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 public
tanı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, gibiClients.All.SendAsync(...)
bir yöntem olmadanawait
çağrılırsa ve hub yöntemi tamamlanmadan önceSendAsync
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
kullanarakClients.All
tüm bağlı istemcilere bir ileti gönderir.SendMessageToCaller
kullanarakClients.Caller
çağırana bir ileti gönderir.SendMessageToGroup
gruptakiSignalR 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ı IChatClient
bir 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 Task
dö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 Promise
döndürür. İstemci kullanarak catch
promise'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
ASP.NET Core