I've been trying to look in the wiki about doing this, I'm following it, but I seem to be missing something?
So here is where I am at:
I have a client side JS that works fine locally.
I now want to send something via an API to update the client side version.I should use SignalR Client right?
This is what i have:
var connection = new HubConnection("http://localhost/test/echo", useDefaultUrl: false);
Global.asax
RouteTable.Routes.MapConnection<MyConnection>("echo", "echo/{*operation}");
I'm getting an error along the lines of no cancellation token is declared....
Is it that I'm not hitting my HubConnection page?
If you need me to clarify let me know.
Thanks,
UPDATE:
Thanks for replying! I'm still uncertain on how a Hub can talk to a persistent connection?
This is what I have so far...
namespace ConnectionHubDemo{
public class ChatHub : Hub
{
public void SendMessage(string message)
{
Clients.NewMessage(message);
}
}
public class ConnectionHub
{
public string test(string data)
{
//Will this talk to my PersistentConnection?
var connection = new HubConnection("http://localhost/test", false);
var myHub = connection.CreateProxy("ConnectionHubDemo.ServiceHub");
//How would I send a message to my persisten connection?
//myHub...
//If succcessful bla bla bla
return data;
}
}
}
That's because you're not using Hubs. You're mixing Hubs and PersistentConnections. On the server Hubs are automatically routed so there's no need to map anything (see https://github.com/SignalR/SignalR/wiki/Hubs). From the wiki:
Unlike low level PersistentConnections, there's no need to specify a route for the hub as they are automatically accessible over a special url (/signalr). This url is configurable:
To make the client side work you just declare a HubConnection with the root url (see https://github.com/SignalR/SignalR/wiki/SignalR-Client-Hubs). Again from the documentation:
To connect to a hub using SignalR, create a HubConnection with the appropriate url.
NOTE: This url will not point to a specific connection. But will instead point to the root of your site.
Example
var connection = new HubConnection("http://mysite/");
So in your case, this would be:
var connection = new HubConnection("http://localhost/test");
Hope this helps.
UPDATE
Hubs DO NOT talk to persistent connections. All you have to do is follow the documentation. My answer above shows how to use Hubs on the server and on the client.
If you want to use Persistent connections then look at the documentation https://github.com/SignalR/SignalR/wiki/PersistentConnection (Server) and https://github.com/SignalR/SignalR/wiki/SignalR-Client (Client).
Related
I have implemented the following javascript code:
var comHub = $.hubConnection();
var comHubProxy = comHub.createHubProxy("chatHub");
registerClientMethods(comHubProxy);
comHubProxy.on("onConnected", function (userName, userList, friendList, groupHistory, groupList, clanList, roomId) {
});
comHub.start().done(function () {
registerEvents(comHubProxy);
});
Where registerClientMethods(..) and registerEvents(..) just declare all my server and client methods. It all works perfectly, but my issue is I have two hubs. This one, and my super secret admin one. oh, super secret I wish.
My issue is I was doing a little checking, and I decided I'd inspect this hub connection. And oh, the horror.
$.connection.hub.proxies
That one line, and hello super secret hub name. Of course, then you can connect and boom hello functions. Now then, yeah they cant just use them, since I have further security measures and checks. But I am uneasy they can even /see/ them! Is there a way to configure my hub setup to only connect to certain hubs depending on the proxy generated? I started attempting it but I'm pretty muddled...
var hubConfig = new HubConfiguration();
hubConfig.EnableDetailedErrors = false;
hubConfig.EnableJavaScriptProxies = true;
app.MapSignalR("/signalr", hubConfig);
app.MapSignalR("/secret", hubConfig);
GlobalHost.HubPipeline.RequireAuthentication();
I am using SQL Server as a backplane for scaling out my SignalR.
In my scenario there are some services which run on other servers and I need to integrate their working status into my SignalR hub.
I tried as a test running a simple Console application with the SQL server scaleout and publish a message like this:
var config = new SqlScaleoutConfiguration(connectionString);
GlobalHost.DependencyResolver.UseSqlServer(connectionString);
var messageBus = new SqlMessageBus(GlobalHost.DependencyResolver, config);
var message = new Message("TransactionHub", "RegisterClient","{userId:1}");
messageBus.Publish(message);
Can I use the SQLScaleout like this somehow?
If not, is there some other way to do what I am trying to do?
Edit:
I've done as halter73 suggested and it works ok, you have to notice that if you activate a client side function, the parameter you send has to match, ie if the object is "Namespace.ClassName" then you should send an object of the same type exactly.
You should try using GlobalHost.ConnectionManager.GetHubContext instead of publishing to the bus directly. Your code would look something like this:
var context = GlobalHost.ConnectionManager.GetHubContext<TransactionHub>();
context.Clients.All.registerClient(new { userId = 1 });
I'm building a secure WebSockets client using C# and the WebSocket4Net library. I would like for all my connections to be proxied through a standard proxy.
This lib uses the SuperSocket.ClientEngine.Common.IProxyConnector to specify a websocket connection's proxy, but I'm not sure how I'm supposed to implement that.
Has anyone worked with this library and can offer some advice?
I had to do the same, to push all websocket connections through Fiddler, for easier debugging. Because the WebSocket4Net author chose to re-use his IProxyConnector interface, System.Net.WebProxy is not directly useable.
On this link the author suggests using the implementations from his parent library SuperSocket.ClientEngine which you can download from CodePlex and include both the SuperSocket.ClientEngine.Common.dll and SuperSocket.ClientEngine.Proxy.dll. I do not recommend this. This causes compiling issues because he (poorly) chose to use the same namespace with both ClientEngine and WebSocket4Net with IProxyConnector defined in both dll's.
What worked for me:
To get it working for debugging through Fiddler, I copied these two classes into my solution, and changed them to the local namespace:
HttpConnectProxy.cs
ProxyConnectionBase
HttpConnectProxy seemed to have a bug on the following line:
if (e.UserToken is DnsEndPoint)
change to:
if (e.UserToken is DnsEndPoint || targetEndPoint is DnsEndPoint)
After that, things worked fine. Sample code:
private WebSocket _socket;
public Initialize()
{
// initialize the client connection
_socket = new WebSocket("ws://echo.websocket.org", origin: "http://example.com");
// go through proxy for testing
var proxy = new HttpConnectProxy(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888));
_socket.Proxy = (SuperSocket.ClientEngine.IProxyConnector)proxy;
// hook in all the event handling
_socket.Opened += new EventHandler(OnSocketOpened);
//_socket.Error += new EventHandler<ErrorEventArgs>(OnSocketError);
//_socket.Closed += new EventHandler(OnSocketClosed);
//_socket.MessageReceived += new EventHandler<MessageReceivedEventArgs>(OnSocketMessageReceived);
// open the connection if the url is defined
if (!String.IsNullOrWhiteSpace(url))
_socket.Open();
}
private void OnSocketOpened(object sender, EventArgs e)
{
// send the message
_socket.Send("Hello World!");
}
I want to be able to send messages to a specific client, I have working code but I cannot find a way to identify users, as on each page load/refresh the client id will change, so I cannot rely on that.
I have tried to append a querystring to the connection, but I have only been able to find the querystring of the same context.
This is my hub, and within the send method i want to be able to match the id that is sent in to a particular connection id at the point of sending the message:
public class Chat : Hub
{
public string addMsg()
{
return "";
}
public void Send(string message, string id)
{
Clients.Client(Context.ConnectionId).receiveMessage(message);
}
}
Here is my client code, i want to pass the id of the person to send a message to to the server send method, and use the querystring value of the other connected user to match it to the id i am sending.
var chat = $.connection.chat;
chat.client.receiveMessage = function (message) {
alert("Received from server: " + message);
};
chat.addMsg = function (message) {
};
$("#sendMessage").click(function () {
chat.server.send($('#newMessage').val(), 6);
});
$.connection.hub.qs = "id=1";
$.connection.hub.start().done(function () {
var myClientId = $.connection.hub.id;
var qs = $.connection.hub.qs;
});
I hope my question makes sense, I have been trying to crack this for a while now, below are some links to some of the articles i have used to get to where i am now, I am just missing the last piece of the puzzle, please go easy on me :)
http://weblogs.asp.net/davidfowler/archive/2012/11/11/microsoft-asp-net-signalr.aspx
SignalR- send data to a specific client
https://github.com/SignalR/SignalR/wiki/QuickStart-Hubs
I don't think this is going to work the way you want it to. The connection ID is just that -- an identifier for a particular connection. SignalR itself doesn't know anything about authenticating users. It is, however, built on top of ASP.NET and all of your familiar authentication methods (Windows, Forms, etc.) work as you would expect.
Once ASP.NET has authenticated the user, you have access to this in your hubs as Context.User. It's now up to you to maintain a mapping between this user and one or more connection IDs. Besides browser refreshes, you might need to deal with a user accessing your service from multiple browsers or machines. Sending a message to this user means sending it to all of those browsers and machines.
Jabbr does all this and more. You really should take a look at that code for a good way to implement this.
How about using the Clients.Caller object int he hub, and overriding the OnConnected method:
public override Task OnConnected()
{
Clients.Caller.sendInitMessage(...);
return base.OnConnected();
}
I have the following project:
server, client, remote object. client does something, then pass the proxy of remote object to the server. All the things work property until server and client are in different domains. Now, when I try to pass result to server I have an exception
"An unhandled exception of type 'System.Runtime.Remoting.RemotingException' occurred in mscorlib.dll
Additional information: This remoting proxy has no channel sink which means either the server has no registered server channels that are listening, or this application has no suitable client channel to talk to the server. "
some sources on Internet says that I need to create some additional channel but I don't know where and how should I do that because I have the channel registration on server and client yet.
Info:
server - domain 2
client - domain 1
remote object - domain 1
Thank you
Sounds like a permissions issue to me. How are you hosting your remoting objects? How are you authenticating across domains? Here's a decent article on some of the issues you might face with auth.
From this article ...
By default, a TCP client channel authenticates itself with the user identity under which the client process is running. You can specify an alternative identity by setting the domain, username, and password properties to specify an alternative identity
Have you specified correct credentials (including domain) on your channel properties?
then pass the proxy of remote object
to the server
Can you explain this? This doesn't sound like a good idea. Typically a proxy is used to invoke remote methods (RPC). Passing the proxy back to the server, doesn't make sense. Sure it may work in some scenarios, but it just adds unnecessary complication.
If you want to pass an object, create a separate data class and pass that as a parameter to the remote method.
Common.dll
[Serializable]
public class Data
{
int a;
int b;
}
[Serializable]
public class ResultData
{
int c;
}
public interface IServerInterface
{
ResultData DoSomething(Data data);
}
Server.dll
public class ServerObject : MarshalByRefObject, IServerInterface
{
public ResultData DoSomething(Data data)
{
// do some work on the server
return new ResultData();
}
}
Client.exe
class Program
{
static void Main(string[] args)
{
IServerInterface proxy = CreateProxy();
ResultData result = proxy.DoSomething(new Data());
}
}