1

I develop a webforms asp.net site with signalr to real time communications.

I have master.page with everything related to signalr defined.

    <%: Scripts.Render("~/Scripts/jquery-1.11.0.min.js") %>
    <%: Scripts.Render("~/Scripts/jquery.signalR-2.0.3.min.js") %>
    <%: Scripts.Render("~/signalr/hubs") %>

In one content page i added another js file to handle signalr stuff, like this:

 $(function () {
            $.connection.hub.start()
                .done(function () {
                    console.log('Now connected, connection ID=' + connection.hub.id);

                });
});

Everything fine!

Then i tried to spread the access to signalR hub to others pages including the master page.

So, i put this in master direct on page:

 <script type="text/javascript">
        $(function () {
            $.connection.hub.start()
                .done(function () {
                    console.log('Now connected MASTER, connection ID=' + $.connection.hub.id);

                });
});
</script>

All fine, but the client connects two time, but with same connectionID. Is there anyhow i can connect just one time and share HubProxy between master and content pages??

But, when i try to render another content page based on that master, i've got a error "hub is undefined".

The only page works ok with that master page is the first one with js separated to signalr.

here is the hub code as required:

 public class GameHub : Hub
    {
        private const long tempoJogada = 30000;
        private const long tempoTruco = 30000;
        private const long tempoMao11 = 30000;

        private readonly static Model.Truco _truco = new Model.Truco();
        private Mesa _mesa;

        private static int JogadoresOnline = 0;

        public GameHub()
        {
            _mesa = _truco.Saloes[0].Mesas[0];

            Debug.WriteLine("criou hub : " + DateTime.Now);
        }

        public List<Jogador> RetornaJogadoresMesa()
        {
            return _mesa.Jogadores;
        }


        public async Task<int> EntrarMesa(Jogador jogador)
        {
            int posicaoMesa = 0;
            Jogador jogadorServer = _mesa.Jogadores.SingleOrDefault(jo => jo.Nome == jogador.Nome);

            jogador.ClientGuid = new Guid(Context.ConnectionId);
            if (_mesa.Jogadores.Count(jo => jo.Nome == jogador.Nome) == 0)
            {

                posicaoMesa = _mesa.EntrarMesa(jogador);
                if (posicaoMesa > 0)
                {
                    await Groups.Add(Context.ConnectionId, _mesa.NomeMesa);
                    Clients.Group(_mesa.NomeMesa).entrarMesa(jogador.Nome, posicaoMesa);
                }


                if (_mesa.QuantidadeVagas == 0)
                {
                    IniciarJogo();
                }
            }
            else
            {
                // ja estava na mesa (reconectando)
                await Groups.Add(Context.ConnectionId, _mesa.NomeMesa);
                if (jogadorServer != null)
                    posicaoMesa = _mesa.Jogadores.IndexOf(jogadorServer) + 1;
            }

            return posicaoMesa;
        }

        private void IniciarJogo()
        {
            EnviaCartas(true);

            _mesa.EstaJogando = true;
        }
.
.
.
.
}

Any suggestions?

Thanks

gilberto
  • 157
  • 3
  • 13
  • why do you want to have only one connection? having the code in the master page only provides the convenience of the sharing the code in all pages, the SignalR javascript api is available so that real time communication between pages is possible, if that is not what you need, maybe you should make the connection using a service layer – Mahmoud Darwish Apr 01 '14 at 10:59
  • ok, but my problem is, when a inserted the script to the master every content page derived from this is getting "hub is undefined". As i mentioned only the first content page i started is working. Thanks – gilberto Apr 01 '14 at 13:46
  • well, for that please post the code of the hub as well, to reproduce the issue – Mahmoud Darwish Apr 01 '14 at 13:49
  • The partial hub code is above. Thanks again, its driving me crazy – gilberto Apr 01 '14 at 14:27

1 Answers1

4

I am not sure this is the cause, but i think maybe its related to how you are referencing the scripts, for me this is how it worked:

1. Define hubs.js

Using the solution from this answer define a js file named hubs.js containing

(function ($) {
    $.ajax({
        url: "/signalr/hubs",
        dataType: "script",
        async: false
    });
}(jQuery));

2. Define a Bundle

In BundleConfig.cs

If you have <asp:ScriptReference Name="jquery" /> in your master page then add

bundles.Add(new ScriptBundle("~/bundles/SignalR").Include(
        "~/Scripts/jquery-1.11.0.min.js",
        "~/Scripts/jquery.signalR-2.0.3.min.js",
        "~/Scripts/hubs.js"));

Else add

bundles.Add(new ScriptBundle("~/bundles/SignalR").Include(
        "~/Scripts/jquery.signalR-2.0.3.min.js",
        "~/Scripts/hubs.js"));

3. Add the Script Reference

And after the bundle add

ScriptManager.ScriptResourceMapping.AddDefinition(
                "signalr",
                new ScriptResourceDefinition
                {
                    Path = "~/bundles/SignalR",
                });

4. Use the Script Reference

In the master page add the following under ScriptManager/Scripts for more info on this check ASP.NET 4.5 ScriptManager Improvements in WebForms

<asp:ScriptManager runat="server">
    <Scripts>
        <asp:ScriptReference Name="jquery" />
        <asp:ScriptReference Name="signalr" />
        .
        .
    </Scripts>
</asp:ScriptManager>

Edit

If the application is not hosted on the root, the hub.js code need to be changed to the following:

(function ($) {
    $.ajax({
        url: "signalr/hubs",
        dataType: "script",
        async: false
    });
}(jQuery));

The leading "/" causes the url to point to the root always

http://domain/signalr/hubs

but without it, it will point to the hosting folder

http://domain/yourAppFolder/signalr/hubs
Community
  • 1
  • 1
Mahmoud Darwish
  • 1,168
  • 1
  • 15
  • 28
  • Thank you very much for your answer. I just keep the scripts out of blundling and minification, to keep the scenario simpler, but actualy it realy seems to be something related to scripts. So i follow your instructions and put back blundle, and the result changed, now the script in the master connects to the hub, but it says "HubProxy is now undefined", by the way, the page i develop first still working with no problems at all(weird). I will go deep tomorrow, and try to figure out. Thanks again – gilberto Apr 04 '14 at 09:35
  • @gilberto you are welcome, maybe the way you defined the scripts was working in the page but not in the master because of your app structure, like the page in the root, but the master in a folder....etc as for the hub proxy, check the edit – Mahmoud Darwish Apr 04 '14 at 17:09
  • it works thank you very much, couldnt vote up due to reputation – gilberto Apr 07 '14 at 05:15
  • @gilberto Iam having the same issue can you tell me where to add ScriptManager.ScriptResourceMapping.AddDefinition( "signalr", new ScriptResourceDefinition { Path = "~/bundles/SignalR", }); – Sreenath Ganga Feb 28 '17 at 20:16