ASP.NET SignalR hub 'Ları API Kılavuzu-sunucu (C#)

by Patrick Fletu, Tom Dykstra

Warning

Bu belge, SignalR 'nin en son sürümü için değildir. ASP.NET Core SignalR'ye göz atın.

Bu belgede, SignalR sürüm 2 için ASP.NET SignalR hub 'ı API 'sinin sunucu tarafını programlama konusunda bir giriş ve ortak seçenekleri gösteren kod örnekleri sunulmaktadır.

SignalR hub 'Ları API 'SI, uzak yordam çağrılarını (RPC) bir sunucudan, istemcilerden ve istemcilerden sunucuya bağlı hale getirmenizi sağlar. Sunucu kodu ' nda, istemciler tarafından çağrılabilen Yöntemler tanımlar ve istemcide çalışan yöntemleri çağırabilirsiniz. İstemci kodunda, sunucudan çağrılabilen yöntemleri tanımlayabilir ve sunucuda çalışan yöntemleri çağırabilirsiniz. SignalR, sizin için istemciden sunucuya sıhhi kını ele alır.

SignalR Ayrıca kalıcı bağlantılar adlı alt düzey bir API sunar. SignalR, hub 'Lar ve sürekli bağlantılara giriş için bkz. SignalR 2 ' ye giriş.

Bu konuda kullanılan yazılım sürümleri

Konu sürümleri

SignalR 'nin önceki sürümleri hakkında daha fazla bilgi için bkz. SignalR daha eski sürümleri.

Sorular ve açıklamalar

Lütfen bu öğreticiyi nasıl beğentireceğiniz ve sayfanın en altındaki açıklamalarda İyileştiğimiz hakkında geri bildirimde bulunun. Öğreticiyle doğrudan ilgili olmayan sorularınız varsa, bunları ASP.NET SignalR forumuna veya StackOverflow.com'e gönderebilirsiniz.

Genel Bakış

Bu belgede aşağıdaki bölümler yer alır:

İstemcilerin programtasyonu hakkındaki belgeler için aşağıdaki kaynaklara bakın:

SignalR 2 için sunucu bileşenleri yalnızca .NET 4,5 'de kullanılabilir. .NET 4,0 çalıştıran sunucularda SignalR v1. x kullanılmalıdır.

SignalR ara yazılımını kaydetme

İstemcilerin hub 'ınıza bağlanmak için kullanacağı yolu tanımlamak için MapSignalR uygulama başladığında yöntemi çağırın. MapSignalR sınıf için bir genişletme yöntemidir OwinExtensions . Aşağıdaki örnek, bir OWıN başlangıç sınıfı kullanarak SignalR hub yolunun nasıl tanımlanacağını göstermektedir.

using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(MyApplication.Startup))]
namespace MyApplication
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // Any connection or hub wire up and configuration should go here
            app.MapSignalR();
        }

    }
}

Bir ASP.NET MVC uygulamasına SignalR işlevselliği ekliyorsanız, SignalR yolunun diğer yollarla önce eklendiğinden emin olun. Daha fazla bilgi için bkz. öğretici: SignalR 2 ve MVC 5 Ile çalışmayabaşlama.

/SignalR URL 'SI

Varsayılan olarak, istemcilerin hub 'ınıza bağlanmak için kullanacağı yol URL 'SI "/SignalR" olarak değişir. (Bu URL 'YI otomatik olarak oluşturulan JavaScript dosyası için olan "/SignalR/Hub" URL 'siyle karıştırmayın. Oluşturulan ara sunucu hakkında daha fazla bilgi için bkz. SignalR hub 'LARı API Kılavuzu-JavaScript istemcisi-oluşturulan ara sunucu ve sizin için ne yapar.)

Bu temel URL 'YI SignalR için kullanılamaz hale getirmek için olağandışı durumlar olabilir; Örneğin, projenizde SignalR adlı bir klasörünüz var ve adı değiştirmek istemezsiniz. Bu durumda, aşağıdaki örneklerde gösterildiği gibi temel URL 'YI değiştirebilirsiniz (örnek kodda "/SignalR" değerini istediğiniz URL ile değiştirin).

URL 'YI belirten sunucu kodu

app.MapSignalR("/signalr", new HubConfiguration());

URL 'YI belirten JavaScript istemci kodu (oluşturulan ara sunucu ile)

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

URL 'YI belirten JavaScript istemci kodu (oluşturulan proxy olmadan)

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

URL 'YI belirten .NET istemci kodu

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

SignalR seçeneklerini yapılandırma

Yönteminin aşırı yüklemeleri MapSignalR , Özel BIR URL, özel bir bağımlılık Çözümleyicisi ve aşağıdaki seçenekleri belirtmenize olanak sağlar:

  • Tarayıcı istemcilerinden CORS veya JSONP kullanarak etki alanları arası çağrıları etkinleştirin.

    Genellikle tarayıcı öğesinden bir sayfa yüklerse http://contoso.com , SignalR bağlantısı ' de aynı etki alanında olur http://contoso.com/signalr . Sayfa http://contoso.com bağlantısı varsa http://fabrikam.com/signalr , etki alanları arası bağlantı olur. Güvenlik nedenleriyle, etki alanları arası bağlantılar varsayılan olarak devre dışıdır. Daha fazla bilgi için bkz. ASP.NET SignalR hub 'LARı API Kılavuzu-JavaScript istemcisi-etki alanları arası bağlantı oluşturma.

  • Ayrıntılı hata iletilerini etkinleştirin.

    Hata oluştuğunda, SignalR 'nin varsayılan davranışı istemcilere ne olduğuna ilişkin ayrıntıları içermeyen bir bildirim iletisi gönderir. Kötü amaçlı kullanıcılar, uygulamanıza karşı saldırılara karşı bilgileri kullanabilabileceğinden, istemcilere ayrıntılı hata bilgileri gönderilmesi, üretimde önerilmez. Sorun giderme için, bu seçeneği kullanarak daha fazla bilgilendirici hata raporlamayı geçici olarak etkinleştirebilirsiniz.

  • Otomatik olarak oluşturulan JavaScript proxy dosyalarını devre dışı bırakın.

    Varsayılan olarak, hub sınıflarınız için proxy 'leri olan bir JavaScript dosyası "/SignalR/Hub" URL 'sine yanıt olarak oluşturulur. JavaScript proxy 'lerini kullanmak istemiyorsanız veya bu dosyayı el ile oluşturmak ve istemcilerinizdeki fiziksel bir dosyaya başvurmak istiyorsanız, ara sunucu oluşturmayı devre dışı bırakmak için bu seçeneği kullanabilirsiniz. Daha fazla bilgi için bkz. SignalR hub 'LARı API Kılavuzu-JavaScript istemcisi-SignalR tarafından oluşturulan ara sunucu için fiziksel dosya oluşturma.

Aşağıdaki örnek, SignalR bağlantı URL 'sinin ve bu seçeneklerin yöntemine yapılan çağrıda nasıl ekleneceğini gösterir MapSignalR . Özel bir URL belirtmek için örnekteki "/SignalR" değerini kullanmak istediğiniz URL ile değiştirin.

var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
hubConfiguration.EnableJavaScriptProxies = false;
app.MapSignalR("/signalr", hubConfiguration);

Hub sınıfları oluşturma ve kullanma

Bir hub oluşturmak için, Microsoft. Aspnet. SignalR. hub' dan türetilen bir sınıf oluşturun. Aşağıdaki örnekte, bir sohbet uygulaması için basit bir hub sınıfı gösterilmektedir.

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

Bu örnekte, bağlı bir istemci NewContosoChatMessage yöntemini çağırabilir ve ne zaman yapıldığında, alınan veriler tüm bağlı istemcilere göre belirlenir.

Hub nesnesi ömrü

Hub sınıfını örnekleyemezsiniz veya kendi kodunuzda kendi kodınızdan yöntemlerini çağıramazsınız; Her şey, SignalR hub 'ı tarafından sizin için yapılır. SignalR, bir istemcinin bağlandığı, bağlantısı kesilen veya sunucuya bir yöntem çağrısı yaptığı zaman gibi bir hub işlemini her işlemesi gerektiğinde hub sınıfınızın yeni bir örneğini oluşturur.

Hub sınıfının örnekleri geçici olduğundan, bir sonraki yöntem çağrısından durumu korumak için bunları kullanamazsınız. Sunucu istemciden bir yöntem çağrısı aldığında, hub sınıfınızın yeni bir örneği iletiyi işler. Birden çok bağlantı ve yöntem çağrısı aracılığıyla durumu korumak için, veritabanı veya hub sınıfında bir statik değişken ya da türemeyen farklı bir sınıf gibi başka bir yöntem kullanın Hub . Hub sınıfında statik değişken gibi bir yöntemi kullanarak verileri bellekte kalıcı hale getirilürse, uygulama etki alanı geri dönüştürüldüğünde veriler kaybolur.

Hub sınıfı dışında çalışan kendi kodlarınızdan istemcilere ileti göndermek istiyorsanız, bir hub sınıfı örneği oluşturarak bunu yapamazsınız, ancak hub sınıfınız için SignalR bağlam nesnesine bir başvuru alarak bunu yapabilirsiniz. Daha fazla bilgi için, bu konunun ilerleyen kısımlarında istemci yöntemlerini çağırma ve hub sınıfının dışından grupları yönetme konularına bakın.

Camel-JavaScript istemcilerinde hub adlarının büyük küçük harfleri

Varsayılan olarak, JavaScript istemcileri, sınıf adının Camel-cased bir sürümünü kullanarak hub 'Lara başvurur. SignalR, JavaScript kodunun JavaScript kurallarına uyum sağlamak için bu değişikliği otomatik olarak yapar. Önceki örneğe contosoChatHub JavaScript kodunda denir.

Sunucu

public class ContosoChatHub : Hub

Oluşturulan proxy kullanan JavaScript istemcisi

var contosoChatHubProxy = $.connection.contosoChatHub;

İstemcilerin kullanması için farklı bir ad belirtmek istiyorsanız, HubName özniteliğini ekleyin. Bir HubName öznitelik kullandığınızda JavaScript istemcilerinde ortası örneğine bir ad değişikliği yapılmaz.

Sunucu

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

Oluşturulan proxy kullanan JavaScript istemcisi

var contosoChatHubProxy = $.connection.PascalCaseContosoChatHub;

Birden çok hub

Bir uygulamada birden çok hub sınıfı tanımlayabilirsiniz. Bunu yaptığınızda bağlantı paylaşılır, ancak gruplar ayrıdır:

  • Tüm istemciler hizmetinize bir SignalR bağlantısı kurmak için aynı URL 'YI kullanır ("/SignalR" veya bir tane belirtilmişse özel URL 'niz) ve bu bağlantı, hizmet tarafından tanımlanan tüm Hub 'Lar için kullanılır.

    Tek bir sınıfta tüm Hub işlevlerini tanımlamaya kıyasla birden çok Hub için performans farkı yoktur.

  • Tüm Hub 'Lar aynı HTTP istek bilgilerini alır.

    Tüm Hub 'Lar aynı bağlantıyı paylaştığından, sunucunun aldığı tek HTTP istek bilgileri, SignalR bağlantısını kuran özgün HTTP isteğine gelir. Bir sorgu dizesi belirterek istemciden sunucuya bilgi geçirmek için bağlantı isteğini kullanırsanız, farklı hub 'Lara farklı sorgu dizeleri sağlayamıyorum. Tüm Hub 'Lar aynı bilgileri alır.

  • Oluşturulan JavaScript proxy 'leri dosyası, tek bir dosyadaki tüm Hub 'Lara ait proxy 'leri içerir.

    JavaScript proxy 'leri hakkında daha fazla bilgi için bkz. SignalR hub 'LARı API Kılavuzu-JavaScript istemcisi-oluşturulan ara sunucu ve sizin için ne yapar.

  • Gruplar, hub 'Lar içinde tanımlanır.

    SignalR 'de, bağlı istemcilerin alt kümelerine yayınlamak için adlandırılmış grupları tanımlayabilirsiniz. Gruplar her Hub için ayrı ayrı tutulur. Örneğin, "Administrators" adlı bir grup sınıfınız için bir istemci kümesi içerir ContosoChatHub ve aynı grup adı sınıfınız için farklı bir istemci kümesine başvuracaktır StockTickerHub .

Strongly-Typed hub 'Ları

İstemcinizin, kuruluşunuzun başvurmasıyla (ve hub yöntemlerinize IntelliSense 'i etkinleştirebileceğinden), hub 'ınızın bir arabirimini tanımlamak için, hub 'ınızı Hub<T> (SignalR 2,1 ' de tanıtılan) şuradan türet Hub :

public class StrongHub : Hub<IClient>
{
    public async Task Send(string message)
    {
        await Clients.All.NewMessage(message);
    }
}

public interface IClient
{
    Task NewMessage(string message);
}

Hub sınıfında istemcilerin çağırabilmeniz için yöntemler tanımlama

Merkezi üzerinde istemciden çağrılabilir olmasını istediğiniz bir yöntemi ortaya çıkarmak için aşağıdaki örneklerde gösterildiği gibi bir genel yöntem bildirin.

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

Herhangi bir C# yönteminde olduğu gibi, karmaşık türler ve diziler dahil olmak üzere bir dönüş türü ve parametreleri belirtebilirsiniz. Parametrelerde aldığınız veya çağırana geri döndürülen tüm veriler, istemci ile sunucu arasında JSON kullanılarak iletilir ve SignalR karmaşık nesnelerin ve nesne dizilerinin otomatik olarak bağlamasını işler.

Camel-JavaScript istemcilerinde yöntem adlarının büyük küçük harfleri

Varsayılan olarak, JavaScript istemcileri, yöntem adının Camel-cased bir sürümünü kullanarak Merkez yöntemlerine başvurur. SignalR, JavaScript kodunun JavaScript kurallarına uyum sağlamak için bu değişikliği otomatik olarak yapar.

Sunucu

public void NewContosoChatMessage(string userName, string message)

Oluşturulan proxy kullanan JavaScript istemcisi

contosoChatHubProxy.server.newContosoChatMessage(userName, message);

İstemcilerin kullanması için farklı bir ad belirtmek istiyorsanız, HubMethodName özniteliğini ekleyin.

Sunucu

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

Oluşturulan proxy kullanan JavaScript istemcisi

contosoChatHubProxy.server.PascalCaseNewContosoChatMessage(userName, message);

Zaman uyumsuz olarak yürütme

Yöntem uzun süre çalışabilir veya bir veritabanı araması veya bir Web hizmeti çağrısı gibi beklemeyi gerektirebilecek iş yapması gerekiyorsa, bir görev ( void dönüş yerinde) veya görev < > T nesnesi (dönüş türü yerine) döndürerek hub yöntemini zaman uyumsuz yapın T . Yönteminden bir nesne döndürdüğünüzde Task , SignalR Task bunun tamamlanmasını bekler ve sarmalanmamış sonucu istemciye geri gönderir; bu nedenle, istemcide yöntem çağrısını nasıl kodlayabilmeniz fark yoktur.

Bir hub yönteminin zaman uyumsuz yapılması, WebSocket aktarımını kullandığında bağlantının engellenmesini önler. Bir hub yöntemi zaman uyumlu olarak yürütülüyorsa ve aktarım WebSocket ise, hub yöntemi tamamlanana kadar hub üzerindeki yöntemlerin sonraki çağrıları aynı istemciden engellenir.

Aşağıdaki örnek, her iki sürümü de çağırmak için çalışan JavaScript istemci kodu tarafından zaman uyumlu veya zaman uyumsuz olarak çalışacak şekilde kodlanmış aynı yöntemi gösterir.

Zaman Uyumlu

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

Zaman uyumsuz

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

Oluşturulan proxy kullanan JavaScript istemcisi

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

ASP.NET 4,5 ' de zaman uyumsuz yöntemlerin nasıl kullanılacağı hakkında daha fazla bilgi için bkz. ASP.NET MVC 4 Içinde zaman uyumsuz yöntemler kullanma.

Aşırı yüklemeleri tanımlama

Bir yöntem için aşırı yüklemeleri tanımlamak istiyorsanız, her aşırı yüklemede parametre sayısı farklı olmalıdır. Farklı parametre türleri belirterek bir aşırı yüklemeyi ayırt ediyorsanız, hub sınıfınız derlenir, ancak istemciler aşırı yüklemelerin birini çağırmaya çalıştığında, çalışma zamanında SignalR hizmeti bir özel durum oluşturur.

Hub yöntemi etkinleştirmeleri üzerinden ilerlemeyi bildirme

SignalR 2,1, .NET 4,5 ' de tanıtılan ilerleme durumu raporlama deseninin desteğini ekler. İlerleme bildirimini uygulamak için, kuruluşunuzun IProgress<T> erişebileceği hub yönteminiz için bir parametre tanımlayın:

public class ProgressHub : Hub
{
    public async Task<string> DoLongRunningThing(IProgress<int> progress)
    {
        for (int i = 0; i <= 100; i+=5)
        {
            await Task.Delay(200);
            progress.Report(i);
        }
        return "Job complete!";
    }
}

Uzun süre çalışan bir sunucu yöntemi yazarken, hub iş parçacığını engellemek yerine zaman uyumsuz/await gibi zaman uyumsuz bir programlama deseninin kullanılması önemlidir.

Hub sınıfından istemci yöntemlerini çağırma

Sunucudan istemci yöntemlerini çağırmak için, Clients özelliği hub sınıfınızın bir yönteminde kullanın. Aşağıdaki örnek, addNewMessageToPage tüm bağlı istemcilere çağıran sunucu kodunu ve bir JavaScript istemcisinde yöntemi tanımlayan istemci kodunu gösterir.

Sunucu

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

İstemci yöntemini çağırmak zaman uyumsuz bir işlemdir ve döndürür Task . Şunu kullanın await :

  • İletinin hatasız gönderildiğinden emin olmak için.
  • Bir try-catch bloğunda yakalama ve işleme hatalarını etkinleştirmek için.

Oluşturulan proxy kullanan JavaScript istemcisi

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

İstemci yönteminden bir dönüş değeri alamazsınız; gibi sözdizimi int x = Clients.All.add(1,1) çalışmıyor.

Parametreler için karmaşık türler ve diziler belirleyebilirsiniz. Aşağıdaki örnek, bir yöntem parametresinde istemciye karmaşık bir tür geçirir.

Karmaşık bir nesne kullanarak istemci yöntemini çağıran sunucu kodu

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

Karmaşık nesneyi tanımlayan sunucu kodu

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

Oluşturulan proxy kullanan JavaScript istemcisi

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

Hangi istemcilerin RPC alacağını seçme

Clients özelliği, hangi istemcilerin RPC alacağını belirtmek için çeşitli seçenekler sağlayan bir Hubconnectioncontext nesnesi döndürür:

  • Tüm bağlı istemciler.

    Clients.All.addContosoChatMessageToPage(name, message);
    
  • Yalnızca çağıran istemci.

    Clients.Caller.addContosoChatMessageToPage(name, message);
    
  • Çağıran istemci dışındaki tüm istemciler.

    Clients.Others.addContosoChatMessageToPage(name, message);
    
  • Bağlantı KIMLIĞIYLE tanımlanan belirli bir istemci.

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

    Bu örnek addContosoChatMessageToPage , çağıran istemciye çağrı yapar ve ile aynı etkiye sahiptir Clients.Caller .

  • Belirtilen istemciler dışındaki tüm bağlı istemciler, bağlantı KIMLIĞIYLE tanımlanır.

    Clients.AllExcept(connectionId1, connectionId2).addContosoChatMessageToPage(name, message);
    
  • Belirtilen bir gruptaki tüm bağlı istemciler.

    Clients.Group(groupName).addContosoChatMessageToPage(name, message);
    
  • Belirtilen bir gruptaki, belirtilen istemciler hariç, bağlantı KIMLIĞIYLE tanımlanan tüm bağlı istemciler.

    Clients.Group(groupName, connectionId1, connectionId2).addContosoChatMessageToPage(name, message);
    
  • Çağıran istemci hariç, belirtilen bir gruptaki tüm bağlı istemciler.

    Clients.OthersInGroup(groupName).addContosoChatMessageToPage(name, message);
    
  • Kullanıcı kimliği tarafından tanımlanan belirli bir kullanıcı.

    Clients.User(userid).addContosoChatMessageToPage(name, message);
    

    Varsayılan olarak, bu, IPrincipal.Identity.Name ancak genel ana bilgisayarıyla bir ıuserıdprovider uygulaması kaydedilerekdeğiştirilebilir.

  • Bir bağlantı kimlikleri listesindeki tüm istemciler ve gruplar.

    Clients.Clients(ConnectionIds).broadcastMessage(name, message);
    
  • Grupların listesi.

    Clients.Groups(GroupIds).broadcastMessage(name, message);
    
  • Ada göre bir kullanıcı.

    Clients.Client(username).broadcastMessage(name, message);
    
  • Kullanıcı adlarının bir listesi (SignalR 2,1 ' de tanıtılan).

    Clients.Users(new string[] { "myUser", "myUser2" }).broadcastMessage(name, message);
    

Yöntem adları için derleme zamanı doğrulaması yok

Belirttiğiniz Yöntem adı dinamik bir nesne olarak yorumlanır, yani bunun için IntelliSense veya derleme zamanı doğrulaması yoktur. İfade çalışma zamanında değerlendirilir. Yöntem çağrısı yürütüldüğünde, SignalR yöntem adını ve parametre değerlerini istemciye gönderir ve istemcinin adıyla eşleşen bir yöntemi varsa, bu yöntem çağrılır ve parametre değerleri kendisine geçirilir. İstemcide eşleşen bir yöntem bulunamazsa, hiçbir hata oluşturulmaz. İstemci yöntemini çağırdığınızda SignalR 'nin arka planda istemciye ilettiği verilerin biçimi hakkında daha fazla bilgi için bkz. SignalR 'ye giriş.

Büyük/küçük harf duyarsız Yöntem adı eşleştirme

Yöntem adı eşleştirme, büyük/küçük harfe duyarlıdır. Örneğin, Clients.All.addContosoChatMessageToPage sunucusunda, AddContosoChatMessageToPage addcontosochatmessagetopage veya istemcisinde yürütülür addContosoChatMessageToPage .

Zaman uyumsuz yürütme

Çağırdığınız yöntem zaman uyumsuz olarak yürütülür. Bir istemciye yönelik bir yöntem çağrısından sonra gelen herhangi bir kod, sonraki kod satırlarının Yöntem tamamlanmasını beklemesi gerekmediği takdirde, SignalR 'nin istemcilere veri aktarma işleminin bitmesini beklemeden hemen yürütülür. Aşağıdaki kod örneği, iki istemci yönteminin sırayla nasıl yürütüleceğini gösterir.

Await kullanma (.NET 4,5)

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

awaitBir sonraki kod satırı çalıştırılmadan önce istemci yöntemi bitene kadar beklemek istiyorsanız, bu, istemcilerin bir sonraki kod çalıştırılmadan önce iletiyi gerçekten alacağı anlamına gelmez. Bir istemci yöntemi çağrısının "tamamlama" işlemi, SignalR 'nin iletiyi göndermek için gereken her şeyi yaptığı anlamına gelir. İstemcilerin iletiyi aldığını doğrulamaya ihtiyacınız varsa, o mekanizmayı kendiniz programlayabilirsiniz. Örneğin, MessageReceived hub 'da bir yöntemi ve istemcide yapmanız addContosoChatMessageToPage MessageReceived gereken herhangi bir işi yaptıktan sonra çağırabilmeniz için istemci üzerindeki yöntemi kodlayın. MessageReceivedHub 'da, gerçek istemci alımı ve özgün yöntem çağrısının işlenmesine bağlı olarak herhangi bir işi yapabilirsiniz.

Yöntem adı olarak bir dize değişkeni kullanma

Bir istemci yöntemini Yöntem adı, atama (veya, vb.) olarak bir dize değişkeni kullanarak çağırmak Clients.All Clients.Others Clients.Caller IClientProxy ve sonra Invoke (MethodName, args...)çağrısı yapmak istiyorsanız.

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

Hub sınıfından grup üyeliğini yönetme

SignalR içindeki gruplar, bağlı istemcilerin belirtilen alt kümelerine ileti yayınlamak için bir yöntem sağlar. Bir grup herhangi bir sayıda istemciye sahip olabilir ve bir istemci herhangi bir sayıda grubun üyesi olabilir.

Grup üyeliğini yönetmek için, hub sınıfının özelliği tarafından sunulan Ekle ve Kaldır yöntemlerini kullanın Groups . Aşağıdaki örnek, Groups.Add Groups.Remove istemci kodu tarafından çağrılan ve ardından onları çağıran JavaScript istemci kodu tarafından kullanılan hub yöntemlerinde kullanılan ve yöntemlerini gösterir.

Sunucu

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

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

Oluşturulan proxy kullanan JavaScript istemcisi

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

Açıkça grup oluşturmanız gerekmez. Aslında bir grup, bir çağrısında adını ilk kez belirttiğinizde otomatik olarak oluşturulur Groups.Add ve içindeki üyeliğinden son bağlantıyı kaldırdığınızda silinir.

Grup üyeliği listesi veya Grup listesi almak için API yok. SignalR bir yayın/alt modelegöre istemcilere ve gruplara iletiler gönderir ve sunucu grup veya grup üyelikleri listesini korumaz. Bu, bir Web grubuna düğüm eklediğiniz her durumda, SignalR 'nin koruduğu tüm durumun yeni düğüme yayılması nedeniyle ölçeklenebilirliği en üst düzeye çıkarmaya yardımcı olur.

Ekleme ve kaldırma yöntemlerinin zaman uyumsuz yürütmesi

Groups.AddVe Groups.Remove yöntemleri zaman uyumsuz olarak yürütülür. Bir gruba istemci eklemek ve grubu kullanarak istemciye hemen ileti göndermek istiyorsanız, öncelikle yöntemin tamamlandığından emin olun Groups.Add . Aşağıdaki kod örneği bunun nasıl yapılacağını göstermektedir.

Bir gruba istemci ekleme ve sonra bu istemciye mesajlaşma

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

Grup üyeliği kalıcılığı

SignalR, kullanıcıları değil bağlantıları izler, bu nedenle Kullanıcı her bağlantı kurduğunda bir kullanıcının aynı grupta olmasını istiyorsanız, Groups.Add Kullanıcı her yeni bağlantı kurduğunda çağrı yapmanız gerekir.

Geçici bir bağlantı kaybı sonrasında, bazı durumlarda SignalR bağlantıyı otomatik olarak geri yükleyebilir. Bu durumda, SignalR aynı bağlantıyı geri yüklüyor, yeni bir bağlantı oluşturmamalıdır ve istemcinin grup üyeliği otomatik olarak geri yüklenir. Bu durum, geçici kesme sunucu yeniden başlatma veya başarısızlık nedeniyle bile, grup üyelikleri de dahil olmak üzere her bir istemcinin bağlantı durumu istemciye yuvarlandığı için mümkündür. Bir sunucu kapalıysa ve bağlantı zaman aşımına uğramadan önce yeni bir sunucu tarafından değiştirilirse, istemci otomatik olarak yeni sunucuya yeniden bağlanabilir ve üyesi olan gruplara yeniden kaydolabilir.

Bağlantı kesilirse veya bağlantı zaman aşımına uğrarsa ya da istemcinin bağlantısı kesildiğinde (örneğin, bir tarayıcı yeni bir sayfaya gittiğinde) bir bağlantı otomatik olarak geri yüklenemediğinde, grup üyelikleri kaybedilir. Kullanıcı bir sonraki sefer bağlanışında yeni bir bağlantı olur. Aynı kullanıcı yeni bir bağlantı kurduğunda grup üyeliklerini sürdürmek için, uygulamanız kullanıcılar ve gruplar arasındaki ilişkilendirmeleri izlemek ve Kullanıcı yeni bir bağlantı kurduğunda grup üyeliklerini geri yüklemek için gerekir.

Bağlantılar ve yeniden bağlantılar hakkında daha fazla bilgi için, bu konunun ilerleyen kısımlarında yer alarak Merkez sınıfında bağlantı ömrü olaylarını işleme bölümüne bakın.

Tek Kullanıcı grupları

SignalR kullanan uygulamalar genellikle hangi kullanıcının bir ileti gönderdiğini ve hangi kullanıcıların bir ileti aldıklarını bilmek için kullanıcılar ve bağlantılar arasındaki ilişkilendirmeleri takip etmelidir. Gruplar, bunu yapmak için yaygın olarak kullanılan iki desenden birinde kullanılır.

  • Tek Kullanıcı grupları.

    Kullanıcı adını Grup adı olarak belirtebilir ve Kullanıcı her bağlandığında veya yeniden bağlandığında geçerli bağlantı KIMLIĞINI gruba ekleyebilirsiniz. Gruba göndereceğiniz kullanıcıya ileti göndermek için. Bu yöntemin bir dezavantajı, grubun, kullanıcının çevrimiçi veya çevrimdışı olduğunu anlamak için bir yol sağlamamasıdır.

  • Kullanıcı adlarıyla bağlantı kimlikleri arasındaki ilişkilendirmeleri izleyin.

    Her Kullanıcı adı ile bir veya daha fazla bağlantı kimliği arasında bir ilişki veya bir sözlükte veya veritabanında bir ilişki saklayabilir ve Kullanıcı her bağlanıp bağlantısı kesildiğinde depolanan verileri güncelleştirebilirsiniz. Kullanıcıya ileti göndermek için bağlantı kimliklerini belirtin. Bu yöntemin bir dezavantajı daha fazla bellek kaplar.

Hub sınıfında bağlantı ömrü olaylarını işleme

Bağlantı ömrü olaylarının işlenmesinin tipik nedenleri, bir kullanıcının bağlanıp bağlanmadığını ve Kullanıcı adları ile bağlantı kimlikleri arasındaki ilişkilendirmeyi takip etmesidir. İstemcileri bağlandığında veya bağlantıyı kestikten sonra kendi kodunuzu çalıştırmak için, OnConnected OnDisconnected OnReconnected Aşağıdaki örnekte gösterildiği gibi hub sınıfının, ve sanal yöntemlerini geçersiz kılın.

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

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

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

OnConnected, OnConnected ve OnConnected çağrıldığında

Her tarayıcı yeni bir sayfaya gittiğinde, yeni bir bağlantı kurulması gerekir. Bu, SignalR 'nin yöntemi ve ardından metodunu yürütecektir anlamına gelir OnDisconnected OnConnected . SignalR yeni bir bağlantı oluşturulduğunda her zaman yeni bir bağlantı KIMLIĞI oluşturur.

OnReconnectedYöntemi, bir kablonun bağlantının zaman aşımına uğramasından önce geçici olarak kesilmesi ve yeniden bağlanması gibi, SignalR 'nin otomatik olarak kurtarabileceği bir bağlantıda geçici bir kesme yapıldığında çağrılır. OnDisconnectedYöntemi, istemcinin bağlantısı kesildiğinde çağrılır ve bir tarayıcı yeni bir sayfaya gittiğinde, SignalR otomatik olarak yeniden bağlanamaz. Bu nedenle, belirli bir istemci için olası bir olay dizisi OnConnected ,, OnReconnected , OnDisconnected veya olur OnConnected OnDisconnected . OnConnected OnDisconnected OnReconnected Belirli bir bağlantı için sırayı görmezsiniz.

OnDisconnectedYöntem, bir sunucunun kapanması ya da uygulama etki alanının geri dönüştürülmesi gibi bazı senaryolarda çağrılmaz. Başka bir sunucu satır üzerine geldiğinde veya uygulama etki alanının geri dönüşümü tamamlandığında, bazı istemciler yeniden bağlanabilir ve olayı tetiklenebilir OnReconnected .

Daha fazla bilgi için bkz. SignalR 'de bağlantı ömrü olaylarını anlama ve işleme.

Çağıran durum doldurulmamış

Bağlantı ömrü olay işleyicisi yöntemleri sunucudan çağrılır, bu, istemcideki nesneye yerleştirdiğiniz herhangi bir durumun state sunucudaki özelliğinde doldurulmayacağı anlamına gelir Caller . stateNesnesi ve özelliği hakkında daha fazla bilgi için Caller , bu konunun ilerleyen kısımlarında istemciler ve Merkez sınıfı arasında durum geçirme konusuna bakın.

Bağlam özelliğinden istemci hakkında bilgi alma

İstemci hakkında bilgi almak için, Context hub sınıfının özelliğini kullanın. ContextÖzelliği, aşağıdaki bilgilere erişim sağlayan bir Hubcallercontext nesnesi döndürür:

  • Çağıran istemcinin bağlantı KIMLIĞI.

    string connectionID = Context.ConnectionId;
    

    Bağlantı KIMLIĞI, SignalR tarafından atanan bir GUID 'dir (değeri kendi kodunuzda belirtemezsiniz). Her bağlantı için bir bağlantı KIMLIĞI vardır ve uygulamanızda birden çok hub varsa, tüm Hub 'Lar tarafından aynı bağlantı KIMLIĞI kullanılır.

  • HTTP üstbilgisi verileri.

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

    Ayrıca, öğesinden HTTP üst bilgilerini de alabilirsiniz Context.Headers . Aynı şey için birden çok başvuru olmasının nedeni Context.Headers ilk olarak oluşturulmuştur, Context.Request özelliği daha sonra eklenmiştir ve Context.Headers geriye dönük uyumluluk için korunur.

  • Sorgu dizesi verileri.

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

    Sorgu dizesi verilerini de alabilir Context.QueryString .

    Bu özelliğe alacağınız sorgu dizesi, SignalR bağlantısını oluşturan HTTP isteğiyle birlikte kullanılmış olan bir dizedir. İstemciden sunucuya istemci hakkında verileri geçirmek için kullanışlı bir yol olan bağlantıyı yapılandırarak istemciye sorgu dizesi parametreleri ekleyebilirsiniz. Aşağıdaki örnek, oluşturulan proxy 'yi kullandığınızda JavaScript istemcisine bir sorgu dizesi eklemenin bir yolunu gösterir.

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

    Sorgu dizesi parametreleri ayarlama hakkında daha fazla bilgi için, JavaScript ve .net istemcileri için API kılavuzlarını inceleyin.

    Sorgu dizesi verilerinde bağlantı için kullanılan aktarım yöntemini, SignalR tarafından dahili olarak kullanılan bazı diğer değerlerle birlikte bulabilirsiniz:

    string transportMethod = queryString["transport"];
    

    Değeri transportMethod "webSockets", "serverSentEvents", "foreverFrame" veya "longPolling" olacaktır. Bu değeri OnConnected olay işleyicisi yönteminde denetlebiliyorsanız, bazı senaryolarda başlangıçta bağlantı için en son anlaşmalı aktarım yöntemi olmayan bir aktarım değeri elde edebilirsiniz. Bu durumda yöntem bir özel durum oluşturur ve daha sonra son taşıma yöntemi oluşturulduğunda yeniden çağrılacaktır.

  • Özgü.

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

    Ayrıca, ' den tanımlama bilgilerini de alabilirsiniz Context.RequestCookies .

  • Kullanıcı bilgileri.

    System.Security.Principal.IPrincipal user = Context.User;
    
  • İstek için HttpContext nesnesi:

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

    HttpContext.Current HttpContext SignalR bağlantısı için nesnenin alınması yerine bu yöntemi kullanın.

İstemcilerle hub sınıfı arasında durum geçirme

İstemci proxy 'si, state her yöntem çağrısıyla sunucuya aktarılmasını istediğiniz verileri depolayabilmeniz için bir nesne sağlar. Sunucusunda, bu verilere Clients.Caller istemciler tarafından çağrılan hub yöntemlerinde özelliğindeki erişebilirsiniz. Clients.CallerÖzelliği, bağlantı ömrü olay işleyicisi yöntemleri OnConnected , ve için doldurulmaz OnDisconnected OnReconnected .

Nesnede veri oluşturma veya güncelleştirme, state Clients.Caller özelliği her iki yönde de çalışacak. Sunucudaki değerleri güncelleştirebilir ve istemciye geri geçirilir.

Aşağıdaki örnek, her yöntem çağrısıyla sunucuya iletilmek üzere durum depolayan JavaScript istemci kodunu gösterir.

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

Aşağıdaki örnek, bir .NET istemcisinde denk kodu gösterir.

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

Hub sınıfınızdan bu verilere Clients.Caller özelliğindeki erişebilirsiniz. Aşağıdaki örnek, önceki örnekte başvurulan durumu alan kodu gösterir.

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

Note

Kalıcı duruma yönelik bu mekanizma büyük miktarlarda veriye yönelik değildir çünkü veya özelliğine yerleştirdiğiniz her şey, state Clients.Caller her yöntem çağrısı ile birlikte yuvarlama yaptığından. Kullanıcı adları veya sayaçlar gibi daha küçük öğeler için faydalıdır.

VB.NET veya türü kesin belirlenmiş bir hub 'da, çağıran durum nesnesine üzerinden erişilemez Clients.Caller ; bunun yerine, kullanın Clients.CallerState (signalr 2,1 ' de tanıtılmıştır):

C 'de CallerState kullanma #

public async Task NewContosoChatMessage(string data)
{
    string userName = Clients.CallerState.userName;
    string computerName = Clients.CallerState.computerName;
    await Clients.Others.addContosoChatMessageToPage(data, userName, computerName);
}

Visual Basic 'de CallerState kullanma

Public Async Function NewContosoChatMessage(message As String) As Task
    Dim userName As String = Clients.CallerState.userName
    Dim computerName As String = Clients.CallerState.computerName
    Await Clients.Others.addContosoChatMessageToPage(message, userName, computerName)
End Sub

Hub sınıfında hataları işleme

Hub sınıfı yöntemleriniz içinde oluşan hataları işlemek için, öncelikle zaman uyumsuz işlemlerden (istemci yöntemlerini çağırma gibi) özel durumları "gözlemleyin" await . Ardından aşağıdaki yöntemlerden birini veya daha fazlasını kullanın:

  • Yöntem kodunuzu try-catch bloklarına sarın ve özel durum nesnesini günlüğe kaydedin. Hata ayıklama amacıyla, özel durumu istemciye gönderebilirsiniz, ancak üretimde istemcilere ayrıntılı bilgi gönderilmesi için güvenlik nedenleriyle önerilmez.

  • OnIncomingError yöntemini Işleyen bir hub işlem hattı modülü oluşturun. Aşağıdaki örnek, hataları kaydeden bir işlem hattı modülünü ve ardından Startup.cs ' deki kodu hub ardışık düzenine çıkartır.

    public class ErrorHandlingPipelineModule : HubPipelineModule
    {
        protected override void OnIncomingError(ExceptionContext exceptionContext, IHubIncomingInvokerContext invokerContext)
        {
            Debug.WriteLine("=> Exception " + exceptionContext.Error.Message);
            if (exceptionContext.Error.InnerException != null)
            {
                Debug.WriteLine("=> Inner Exception " + exceptionContext.Error.InnerException.Message);
            }
            base.OnIncomingError(exceptionContext, invokerContext);
    
        }
    }
    
    public void Configuration(IAppBuilder app)
    {
        // Any connection or hub wire up and configuration should go here
        GlobalHost.HubPipeline.AddModule(new ErrorHandlingPipelineModule()); 
        app.MapSignalR();
    }
    
  • Sınıfını kullanın HubException (SignalR 2 ' de tanıtılan). Bu hata herhangi bir hub çağrısından oluşturulabilir. HubErrorOluşturucu bir dize iletisi ve ek hata verilerini depolamak için bir nesnesi alır. SignalR, özel durumu otomatik olarak serileştirmesini ve istemciye göndermesini, bu da hub yöntemi çağrısını reddetmek veya devretmek için kullanılacaktır.

    Aşağıdaki kod örnekleri HubException , bir hub çağrısı sırasında nasıl oluşturulacağını ve JavaScript ve .net istemcilerindeki özel durumun nasıl işleneceğini gösterir.

    HubException sınıfını gösteren sunucu kodu

    public class MyHub : Hub
    {
        public async Task Send(string message)
        {
            if(message.Contains("<script>"))
            {
                throw new HubException("This message will flow to the client", new { user = Context.User.Identity.Name, message = message });
            }
    
            await Clients.All.send(message);
        }
    }
    

    Bir hub 'da HubException oluşturma yanıtını gösteren JavaScript istemci kodu

    myHub.server.send("<script>")
                .fail(function (e) {
                    if (e.source === 'HubException') {
                        console.log(e.message + ' : ' + e.data.user);
                    }
                });
    

    Bir hub 'da HubException oluşturma yanıtını gösteren .NET istemci kodu

    try
    {
        await myHub.Invoke("Send", "<script>");
    }
    catch(HubException ex)
    {
        Console.WriteLine(ex.Message);
    }
    

Merkez ardışık düzen modülleri hakkında daha fazla bilgi için, bu konunun ilerleyen bölümlerinde hub işlem hattını Özelleştirme bölümüne bakın.

İzlemeyi etkinleştirme

Sunucu tarafı izlemeyi etkinleştirmek için, aşağıdaki örnekte gösterildiği gibi Web.config dosyanıza bir System. Diagnostics öğesi ekleyin:

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

Uygulamayı Visual Studio 'da çalıştırdığınızda, günlükleri Çıkış penceresinde görebilirsiniz.

İstemci yöntemlerini çağırma ve grupları hub sınıfı dışından yönetme

Hub sınıfınızın farklı bir sınıfından istemci yöntemlerini çağırmak için, Hub için SignalR bağlam nesnesine bir başvuru alın ve bunu istemci üzerindeki yöntemleri çağırmak veya grupları yönetmek için kullanın.

Aşağıdaki örnek StockTicker sınıf, bağlam nesnesini alır, sınıfının bir örneğinde depolar, sınıf örneğini statik bir özellikte depolar ve updateStockPrice adlı bir hub 'a bağlı istemcilerde yöntemi çağırmak için Singleton sınıf örneğinden bağlamını kullanır StockTickerHub .

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

    private IHubContext _context;

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

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

İçeriği uzun süreli bir nesnede birden çok kez kullanmanız gerekiyorsa, başvuruyu bir kez alın ve her seferinde yeniden almak yerine kaydedin. Bağlam bir kez alındıktan sonra, SignalR 'nin, hub yöntemlerinizin istemci yöntemi etkinleştirmeleri haline gelen aynı sıradaki istemcilere ileti göndermesi güvence altına alınır. Bir hub için SignalR bağlamını nasıl kullanacağınızı gösteren bir öğretici için, bkz. ASP.NET SignalR Ile sunucu yayını.

İstemci yöntemlerini çağırma

Hangi istemcilerin RPC alacağını belirtebilirsiniz, ancak bir hub sınıfından çağrı yaparken daha az seçeneğiniz olur. Bunun nedeni, bağlamın bir istemciden gelen belirli bir çağrıyla ilişkilendirilmediği, yani veya gibi geçerli bağlantı KIMLIĞI hakkında bilgi gerektiren tüm yöntemlerin mevcut olmadığından emin değildir Clients.Others Clients.Caller Clients.OthersInGroup . Aşağıdaki seçenekler kullanılabilir:

  • Tüm bağlı istemciler.

    context.Clients.All.addContosoChatMessageToPage(name, message);
    
  • Bağlantı KIMLIĞIYLE tanımlanan belirli bir istemci.

    context.Clients.Client(connectionID).addContosoChatMessageToPage(name, message);
    
  • Belirtilen istemciler dışındaki tüm bağlı istemciler, bağlantı KIMLIĞIYLE tanımlanır.

    context.Clients.AllExcept(connectionId1, connectionId2).addContosoChatMessageToPage(name, message);
    
  • Belirtilen bir gruptaki tüm bağlı istemciler.

    context.Clients.Group(groupName).addContosoChatMessageToPage(name, message);
    
  • Belirtilen bir gruptaki, belirtilen istemciler hariç, bağlantı KIMLIĞIYLE tanımlanan tüm bağlı istemciler.

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

Hub 'ınızdaki yöntemlerden hub olmayan sınıfa çağrı yapıyorsanız, geçerli bağlantı KIMLIĞINI geçirebilir ve, Clients.Client Clients.AllExcept Clients.Group veya benzetimini yapmak için, Clients.Caller Clients.Others ya da kullanabilirsiniz Clients.OthersInGroup . Aşağıdaki örnekte, sınıfı, sınıfının MoveShapeHub benzetimini yapabilmesi için bağlantı kimliğini sınıfına geçirir Broadcaster Broadcaster Clients.Others .

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

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

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

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

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

Grup üyeliğini yönetme

Grupları yönetmek için bir hub sınıfında yaptığınız seçeneklerle aynı seçeneklere sahip olursunuz.

  • Bir gruba istemci ekleme

    context.Groups.Add(connectionID, groupName);
    
  • Bir gruptan bir istemciyi kaldırma

    context.Groups.Remove(connectionID, groupName);
    

Hub ardışık düzenini özelleştirme

SignalR, kendi kodunuzu hub işlem hattına eklemenizi sağlar. Aşağıdaki örnek, istemcisinde çağrılan her bir gelen yöntem çağrısını günlüğe kaydeden özel bir hub işlem hattı modülünü ve istemcide çağrılan giden yöntem çağrısını gösterir:

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

Startup.cs dosyasında aşağıdaki kod, modülü hub işlem hattında çalışacak şekilde kaydeder:

public void Configuration(IAppBuilder app) 
{ 
    GlobalHost.HubPipeline.AddModule(new LoggingPipelineModule()); 
    app.MapSignalR();
}

Geçersiz kılabileceğiniz birçok farklı yöntem vardır. Tüm liste için bkz. Hubpipelinemodule yöntemleri.