Использовать методы концентратора из контроллера?

Я использую SignalR 2 и не могу понять, как я могу использовать методы концентратора, например, из действия контроллера.

Я знаю, что могу сделать следующее:

var hub = GlobalHost.ConnectionManager.GetHubContext<T>();
hub.Clients.All.clientSideMethod(param);

Но это выполняет метод непосредственно на стороне клиента.

Что, если у меня есть бизнес-логика внутри моего метода ClientSideMethod(param) на стороне сервера, который я хочу вызывать из моего контроллера так же, как когда он вызывается со стороны клиента?

На данный момент я использую public static void ClientSideMethod(param) внутри своего хаба, и в этом методе я использую IHubContext из ConnectionManager.

Разве нет лучшего способа сделать это?

Следующее не работает (уже в SignalR 2?):

var hubManager = new DefaultHubManager(GlobalHost.DependencyResolver);
instance = hubManager.ResolveHub(typeof(T).Name) as T;
instance.ClientSideMethod(param);

Там я получаю исключение «Концентратор, не созданный через конвейер концентратора, не поддерживаемый» при доступе к клиентам.


person Christoph Fink    schedule 27.07.2013    source источник
comment
Почему бы не сделать это с клиента, который, как я полагаю, является JS, вы можете сделать запрос Ajax и сделать то, что вам нужно, на контроллере.   -  person Mahmoud Darwish    schedule 28.07.2013
comment
@MEYWD: Потому что, например, у меня есть интерфейс администратора, который я хотел бы обновлять, когда что-то происходит. Например. клиент посещает определенную страницу, поэтому я хотел бы вызвать метод концентратора в действии контроллера с этой страницы. Настоящего клиента это не волнует, так зачем ему публиковать это сообщение?   -  person Christoph Fink    schedule 28.07.2013
comment
я сделал что-то подобное, у меня есть клиенты и админы (специальный клиент), админ отправляет команду и ждет ответа от клиента, для этого я сделал список админов и список клиентов на хабе, админ выбирает клиента, резервирует его, чтобы его не использовал другой администратор, затем отправляет команду, хаб ретранслирует ее клиенту, клиент возвращает ответ хабу, который, в свою очередь, ретранслируется администратору, и ответ печатается на экран   -  person Mahmoud Darwish    schedule 28.07.2013


Ответы (2)


может создать "вспомогательный" класс, который реализует ваши бизнес-правила и вызывается как вашим концентратором, так и вашим контроллером:

public class MyHub : Hub
{
    public void DoSomething()
    {
        var helper = new HubHelper(this);
        helper.DoStuff("hub stuff");
    }
}

public class MyController : Controller
{
    public ActionResult Something()
    {
        var hub = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
        var helper = new HubHelper(hub);
        helper.DoStuff("controller stuff");
    }
}

public class HubHelper
{
    private IHubConnectionContext hub;

    public HubHelper(IHubConnectionContext hub)
    {
        this.hub = hub;
    }

    public DoStuff(string param)
    {
        //business rules ...

        hub.Clients.All.clientSideMethod(param);
    }
}
person michaelrp    schedule 27.07.2013
comment
+1, так как это уже лучший подход, чем мой, но я все же хотел бы иметь возможность напрямую использовать методы концентратора, поскольку мне это кажется более понятным и понятным... - person Christoph Fink; 27.07.2013
comment
@ChrFin, вы когда-нибудь находили способ успешно вызывать методы концентратора из сборки? Без возможности вызова экземпляра концентратора этот вариант кажется наиболее СУХИМ и разрозненным. - person Brandon Wittwer; 13.08.2014
comment
@BrandonWittwer: Нет, не совсем так. Я просто не пометил ответ как принятый, так как все еще надеюсь на собственное решение. Я добавлю ответ с моим решением, которое у меня есть на данный момент... - person Christoph Fink; 13.08.2014

Поскольку я не нашел «хорошего решения», я использую решение @michael.rp с некоторыми улучшениями:

Я создал следующий базовый класс:

public abstract class Hub<T> : Hub where T : Hub
{
    private static IHubContext hubContext;
    /// <summary>Gets the hub context.</summary>
    /// <value>The hub context.</value>
    public static IHubContext HubContext
    {
        get
        {
            if (hubContext == null)
                hubContext = GlobalHost.ConnectionManager.GetHubContext<T>();
            return hubContext;
        }
    }
}

А затем в реальном концентраторе (например, public class AdminHub : Hub<AdminHub>) у меня есть (статические) методы, подобные следующим:

/// <summary>Tells the clients that some item has changed.</summary>
public async Task ItemHasChangedFromClient()
{
    await ItemHasChangedAsync().ConfigureAwait(false);
}
/// <summary>Tells the clients that some item has changed.</summary>
public static async Task ItemHasChangedAsync()
{
    // my custom logic
    await HubContext.Clients.All.itemHasChanged();
}
person Christoph Fink    schedule 13.08.2014