SignalR backplane expected behavior - signalr

I'm creating a new SignalR (.net core) backplane and I'm a little confused about the backplane's expected behavior.
Send all: Is this restricted to all within a hub type or to all hubs of any type across the entire network?
Send to Group: Simalar question. Should I only be sending to groups within a hub type? Or should I send a group message to all subscribers of a group by name - regardless of the source or destination hub type?
Send to User: Also similar question. Should I send the message to all instances of the user, regardles of hub type? Or should I restrict sending to only same user instances of the source hub type?

The HubLifetimeManager class is generic with the hub type as the generic type. So it follows that the methods you implement only apply to the specific hub type.

I think I found the answer to my question in the source for the Microsoft.AspNetCore.SignalR.StackExchangeRedis backplane.
It seems all message channels are prefixed with the type.FullName of the hub. So send-all, send-to-group, and send-to-user messages are always scoped to the Hub type doing the sending.
So all mesages are always (and only) received by hubs of the same type. And no messages sent from other hub types should ever be received by said hub!
Please correct me if I'm wrong about this. Having the wrong paradigm will reak havoc on my backplane. Which I hope to make public as soon as it's done.

Related

SignalR hub is shortlived

I have a self hosted webApi project in a desktop C# application. This uses Microsoft.Owin.Hosting.WebApp.
I have a Hub derived class that has a send and a receive from an angular client.
The hub is instanced by the WebApp.start. I find that it is short lived. When the client sends a message, the hub is instanced and then disposed. I need to send message to the client, but I don't have an instance of the hub to send a message in the other direction.
At one point, I was holding a reference to the instance (as in memory leak) and I could get a message to the client.
The client shows as it is always connected. No disconnected messages.
What am I missing?
You should not hold this instance by yourself and you shold never create an instance by yourself.
Read the details about the hub onject life time here:
https://learn.microsoft.com/en-us/aspnet/signalr/overview/guide-to-the-api/hubs-api-guide-server#hub-object-lifetime
In the case you need to send a message to the connected clients you need to use GetHubContext.
Example:
var context = GlobalHost.ConnectionManager.GetHubContext<yourHub>();
context.Clients.All.Send("Something");
(In the case you are using core signalr read: Call SignalR Core Hub method from Controller)

Connected to multiple hubs and disconnect from only one

I'm writing a Single Page Application with Durandal and I'm planning on using SignalR for some functionality. First of all, I have a top bar that listens for notifications that the server may send. The site start a connection to the "TopBarNotificationHub".
On one of the pages I want to connection to another hub as two users might edit the data on this page simultaneous and I want to notify if someone updated the data. No problem, this works fine.
But, when leaving that page I want to disconnect from ONLY the second hub, but I can't find a way to accomplish this. If I just say hub.connection.stop(); the connection to th eTopBarNotificationHub also stops (as it's shared).
Is there a way to just leave one hubproxy and let the other exist?
As this is a SPA the "shell" is never reloaded so it doesn't connect to the hub again... I might be able to force this to reconnect everytime another page disconnects from a hub, but there might be a cleaner solution...
Thanks in advance.
//J
If you use multiple hubs on a single page that's fine, but they share the same connection, so it isn't taking up more resources on the client other than receiving the updates.
Therefore to "connect and disconnect to/from a hub" you need to slightly rearchitect. If you use Groups instead of Clients on the server side you can "register" with a Hub by calling a (for example) Hub1.Register method and sticking the client in the relevant group in that method. To "deregister" you call a (for example) Hub1.DeRegister and remove the client's ConnectionId from the group in that method. Then, when you push updates to clients, you can just use the Group instead of Clients.All.
(C# assumed for server language as you didn't specify in your tag)
To add a client to the hub group: Groups.Add(Context.ConnectionId, groupNameForHub);
To remove a client from the hub group: Groups.Remove(Context.ConnectionId, id.ToString());
To broadcast to that Hub's clients: Clients.Group(groupNameForHub).clientMethodName(param1, param2);
Just to make it confusing, though, note that the group named "myGroup" in Hub1 is separate to the group named "myGroup" in Hub2.
This is the exact approach recommended in the documents (copied here in case they move/change in later versions):
Multiple Hubs
You can define multiple Hub classes in an application. When you do that, the connection is shared but groups are separate:
• All clients will use the same URL to establish a SignalR connection with your service ("/signalr" or your custom URL if you specified one), and that connection is used for all Hubs defined by the service.
There is no performance difference for multiple Hubs compared to defining all Hub functionality in a single class.
• All Hubs get the same HTTP request information.
Since all Hubs share the same connection, the only HTTP request information that the server gets is what comes in the original HTTP request that establishes the SignalR connection. If you use the connection request to pass information from the client to the server by specifying a query string, you can't provide different query strings to different Hubs. All Hubs will receive the same information.
• The generated JavaScript proxies file will contain proxies for all Hubs in one file.
For information about JavaScript proxies, see SignalR Hubs API Guide - JavaScript Client - The generated proxy and what it does for you.
• Groups are defined within Hubs.
In SignalR you can define named groups to broadcast to subsets of connected clients. Groups are maintained separately for each Hub. For example, a group named "Administrators" would include one set of clients for your ContosoChatHub class, and the same group name would refer to a different set of clients for your StockTickerHub class.

SignalR: Why choose Hub vs. Persistent Connection?

I've been searching and reading up on SignalR recently and, while I see a lot of explanation of what the difference is between Hubs and Persistent Connections I haven't been able to get my head around the next level, which is why would I choose one approach over the other?
From what I see in the Connection and Hubs section it seems that Hubs provide a topic system overlaying the lower-level persistent connections.
From the highly up-voted comment below:
Partially correct. You can get topics or groups in persistent connections as well. The big difference is dispatching different types of messages. For example you have different kinds of messages and you want to send different kinds of payloads. With persistent connections you have to embed the message type in the payload (see Raw sample) but hubs gives you the ability to do RPC over a connection (lets you call methods on on the client from the server and from the server to the client). Another big thing is model binding. Hubs allow you to pass strongly typed parameters to methods.
The example used in the documentation uses a chat room metaphor, where users can join a specific room and then only get messages from other users in the same room. More generically your code subscribes to a topic and then get just messages published to that topic. With the persistent connections you'd get all messages.
You could easily build your own topic system on top of the persistent connections, but in this case the SignalR team did the work for you already.
The main difference is that you can't do RPC with PersistentConnection, you can only send raw data. So instead of sending messages from the server like this
Clients.All.addNewMessageToPage(name, message);
you'd have to send an object with Connection.Broadcast() or Connection.Send() and then the client would have to decide what to do with that. You could, for example, send an object like this:
Connection.Broadcast(new {
method: "addNewMessageToPage",
name: "Albert",
message: "Hello"
});
And on the client, instead of simply defining
yourHub.client.addNewMessageToPage = function(name, message) {
// things and stuff
};
you'd have to add a callback to handle all incoming messages:
function addNewMessageToPage(name, message) {
// things and stuff
}
connection.received(function (data) {
var method = data.method;
window[method](data.name, data.message);
});
You'd have to do the same kind of dispatching on the server side in the OnReceived method. You'd also have to deserialize the data string there instead of receiving the strongly typed objects as you do with hub methods.
There aren't many reasons to choose PersistentConnection over Hubs. One reason I'm aware of is that it is possible to send preserialized JSON via PersistentConnection, which you can't do using hubs. In certain situations, this might be a relevant performance benefit.
Apart from that, see this quote from the documentation:
Choosing a communication model
Most applications should use the Hubs API. The Connections API could
be used in the following circumstances:
The format of the actual message sent needs to be specified.
The developer prefers to work with a messaging and dispatching model
rather than a remote invocation model.
An existing application that uses a messaging model is being ported to use SignalR.
Depending on your message structure, you might also get small perfomance benefits from using PersistentConnection.
You may want to take a look at the SignalR samples, specifically this here.
There are two ways to use SignalR: you can access it at a low level by overriding its PersistentConnection class, which gives you a lot of control over it; or you can let SignalR do all of the heavy lifting for you, by using the high level ‘Hubs’.
Persistent Connection is a lower level API, you can perform actions on more specific time when the connection is opened or closed, in most applications the Hub is the best choice
There are three major points to consider when comparing these two:
Message Format
Communication model
SignalR customization
With hubs message formatting is basically handled from you but with persistent connections the message is raw and has be tokenized and parsed back and forth. If the message size is important then also note that the payload of a persistent connection is much less that that of a hub.
When it comes to the communication model persistent connections basically have a function for sending and receiving messaging while hubs take a remote procedure call model with unique function per requirement.
When it comes to customization since persistent connections are more low level they may give you more control over customization.

How can I Manually create a client proxy for a WF4 (xamlX) Service

I've created several services by wrapping the WorkflowServiceHost in a WCF service; using WorkflowHostingEndpoint. Doing this I was able to define my service contract and create proxy classes to connect to those services.
I'm now creating a service in which I want to use the WF4 messaging activities and again self host the service. I also REALLY want to manually create my proxy classes without using the ServiceReference in VS2010 or ServiceUtil...
I've seen some references that use the Send Activity in the Service client but I'd like to be able to use a more "WCF-like" proxy created directly against the service contract like I've done with the other services. How can I do that? Is there anywhere a xamlX (or xaml with messaging activities) stores the interface contract that I can use to generate a proxy manually?
NOTE: I don't want to use the Send activity as described in the WF_WCF_Samples.
UPDATE:
I tried creating an interface identical to the workflow receive activity before posting this question; but I keep getting the following error:
The message with Action 'http://tempuri.org/ISvrClientService/Create'
cannot be processed at the receiver, due to a ContractFilter mismatch
at the EndpointDispatcher. This may be because of either a contract
mismatch (mismatched Actions between sender and receiver) or a
binding/security mismatch between the sender and the receiver. Check
that sender and receiver have the same contract and the same binding
(including security requirements, e.g. Message, Transport, None).
Thanks!
There is no need to use the Send activity. When you host a workflow service you are hosting a SOAP endpoint, the only difference is the implementation but that is a private detail. You can create a proxy object using ChannelFactory just like with any other WCF service.
var factory = new ChannelFactory<IYourService>();
var proxy = factory.CreateChannel();
The IYourService interface is somethign you have to hand craft. There isn't one on the server, it is done in a workflow, so you have to code up the identical contract.
I've done this successfully with channel factory and manually created interfaces. The trick was in matching-up the reply/send in/out parameters names not just type signature.
This is particularly crucial if you have bookmarks with correlation in your workflow.

Biztalk, need to consume a web service

What I need to do to send a request and to receive answer from the Web Service that I want to consume.
What i have done:
I have done the "add web Reference"
I added a Send Shape and a Receive Shape and a I configured a port that sent and received with web Type, the port binding Specify later and I connect with the Request and response to the Send and Receive shape.
I believe I am missing something ?
From your description I am guessing you might be missing -
A definition of the request and
response messages; you need to
ensure you have a request and
response message defined, with their
types being the generated web types.
Select the correct message for both
the send and receive shape. send
shape uses the request message,
receive shape uses the response
message.
Construct the request message using a construct and a transform or assignment shape before the send shape. the easiest way to get started is to use a map in a transform shape to create the request from whatever message triggered your process, but the exact implementation detail will, of course, depend on your scenario
This should be enough to call the service I would have thought
There are many blog posts on the subject, here's one I found with a quick search that shows all the pieces needed
I'm currently working my way through a project using Biztalk to consume a web service. I think you may have a error when compiling similar to :
"Use of unreconstructed message"
If this is the problem, add a construct message shape to the orchestration before the send to the web service port.
I'm stuck with creating the message syntax but this should get you moving.

Resources