locked
Which is the better way to integrate SignalR with WCF? RRS feed

  • Question

  • User-1158769213 posted

    Hello,

    We have a mature application which consists of a WPF desktop app that uses WCF services for data access. We are looking to integrate SignalR to enable us to pass messages from one user to another (eg, notify everyone else when a user updates a customer).

    I'm looking for advice on the best way to do this. I can see three options so far, but am open to suggestions on others...

    1. Rewrite all of our WCF services using SignalR, so instead of calling a WCF service to update a customer, the desktop app would call a SignalR hub method. That server-side method would do whatever the equivalent WCF service call does now, as well as send out a message to the other users.
    2. Leave our current client code as it is, but add code in the WCF service call to grab the hub context and send out a message when a customer is updated. You can see a simple sample of what I mean in the code I posted in this question the other day.
    3. Don't touch the WCF stuff at all and add some SignalR code side-by-side. This would mean that anywhere the client app made a WCF call, it would then immediately make a call to the SignalR hub, which would then pass the message on to other users.

    Out of these, 1 is the most work, but ends up with the neatest code. All client-server communication is done via SignalR. However, I'm not sure if SignalR was designed for this sort of thing. Are there any issues (other than the amount of work needed to go down this route) with doing it this way?

    Option 2 is fairly simple, but has the disadvantage that as we are calling into the hub from outside of the SignalR channel, the hub won't know which client sent the message, so can only broadcast the reply to everyone. I can use Clients.Others in this case. It also has the disadvantage over option 1 that we need to add an extra line of code to each WCF service call to do the SignalR stuff.

    Option 3 is clean in that it keeps the WCF and SignalR areas completely separate, but means more code (the client app has to make a second call - SignalR - after making the WCF call, even though the payload is exactly the same), which means more bandwidth.

    Any comments as to which is the better option? Thanks

    Thursday, April 12, 2018 1:58 PM

All replies

  • User475983607 posted

    I would use optimistic concurrency rather than SignalR for this sort of design as optimistic concurrency is going to be far more performant and less error prone.  Keep in mind, SignalR is HTTP real-time not real real-time.  There is latency in HTTP requests. It is possible and very likely in a busy application to have more than one concurrent HTTP request in process. 

    If the ultimate goal is fixing dirty data making its way into the data stores due to concurrency then you'll need optimistic concurrency anyway.  Once optimistic concurrency is implemented, SignalR is becomes a "nice to have" user interface feature as the optimistic concurrency handles, well, the concurrency.

    Thursday, April 12, 2018 2:17 PM
  • User-1158769213 posted

    Hello, thanks for the reply.

    The HTTP delay isn't an issue for us, as we don't have enough users (and have enough customers in the database) that the chances of data corruption are very small. We're mainly looking at SignalR as a way of keeping everyone's UI updated with changes, so the HTTP delay isn't really an issue.

    Edit: To clarify the above, we already have optimistic concurrency implemented at the database level, so that's not really what we're trying to achieve here. Our aim is to update the clients with changes that other users have made.

    Does that alter what you would say to my original question?

    Thanks again.

    Thursday, April 12, 2018 2:56 PM
  • User475983607 posted

    So SignalR is a "nice to have" feature....

    I would design the clients (WPF) to listen for a update events from the service and let the clients determine whether to refresh the content or not.   I assume you'll need to come up with a message protocol so the client can determine if they need to refresh the UI with new data.

    Thursday, April 12, 2018 3:29 PM
  • User-1158769213 posted

    Thanks for the reply. However, you've confused me!

    From your second paragraph, it sounds like you're suggesting not using SignalR, but designing our own mechanism for receiving notifications from the server. Isn't that exactly what SignalR was designed to do? If so, aren't you suggesting we reinvent the wheel? Please explain what I missed.

    The way I was thinking (irrespective of which method I used) was that the clients would receive a message, and then decide what to do with the data. In most cases, they would update the local copy of the data (say the specific customer in the local customer list which was loaded when the client app started), but they may decide to do other things with it as well, or just ignore it.

    Please clarify as I've obviously missed something here. Thanks again

    Thursday, April 12, 2018 3:37 PM
  • User475983607 posted

    Yossu

    Thanks for the reply. However, you've confused me!

    From your second paragraph, it sounds like you're suggesting not using SignalR, but designing our own mechanism for receiving notifications from the server. Isn't that exactly what SignalR was designed to do? If so, aren't you suggesting we reinvent the wheel? Please explain what I missed.

    The way I was thinking (irrespective of which method I used) was that the clients would receive a message, and then decide what to do with the data. In most cases, they would update the local copy of the data (say the specific customer in the local customer list which was loaded when the client app started), but they may decide to do other things with it as well, or just ignore it.

    Please clarify as I've obviously missed something here. Thanks again

    Sorry for the confusion, the context is still SignalR.  Since SignalR uses websockets, I though the use of the words "listen" and "message protocol" were appropriate.  

    Thursday, April 12, 2018 3:42 PM
  • User-1158769213 posted

    Phew, that's a relief! Thanks for the clarification.

    OK, so we're still with SignalR, it sounds to me like you're suggesting we go with option 2 from my first post? If so, is there a way to get around the fact that when we send the message out from the server, we have to use Clients.All, meaning that the client that updated the customer also gets a message? Not the end of the world, and we can add some GUID to the message so the client can check, but it's all extra code. Be nice if we could use the Clients.Others goodness that SignalR has built in.

    Thanks again.

    Thursday, April 12, 2018 3:46 PM
  • User475983607 posted

    Yossu

    Phew, that's a relief! Thanks for the clarification.

    OK, so we're still with SignalR, it sounds to me like you're suggesting we go with option 2 from my first post? If so, is there a way to get around the fact that when we send the message out from the server, we have to use Clients.All, meaning that the client that updated the customer also gets a message? Not the end of the world, and we can add some GUID to the message so the client can check, but it's all extra code. Be nice if we could use the Clients.Others goodness that SignalR has built in.

    Thanks again.

    IMHO, this requirements is extra code that serves no purpose other than to cause head scratching puzzlement at a later time when there is no response to some clients.  Keep it clean.   The server fires an event and listeners handle the event.  Perhaps think of the response as a confirmation for the sender.  

    Thursday, April 12, 2018 4:01 PM
  • User-1158769213 posted

    Sorry, you've lost me again!

    IMHO, this requirements is extra code that serves no purpose other than to cause head scratching puzzlement at a later time when there is no response to some clients.  Keep it clean.

    Why doesn't it serve a purpose? If one user modifies a customer, then this feature will allow other users to see the updated information without having to refresh their customer list. Seems like a very good idea to me, and is something our clients want.

    Also, why shouldn't there be a response to some clients? If SignalR sends out a message, why wouldn't the clients get it? Obviously there is always the issue of connectivity, lost connections, etc, but that's something we have to contend with anyway.

    The server fires an event and listeners handle the event.  Perhaps think of the response as a confirmation for the sender.  

    Lost me completely here!

    If we're talking about SignalR, then in all three of my options earlier the server sends out a message (I assume that's what you mean by an event), and the clients (the listeners) handle it. The only difference between the options is whether we use SignalR for the message the client sends to the server (option 1, where we use SignalR in place of WCF), or stick with WCF for the client to server message, and then either have the WCF service call use SignalR to broadcast a message (option 2) or have the client send a second message to the server, this time specifically to the SignalR hub as opposed to the WCF service. In all three options, the server sends out a SignalR message and the clients handle it.

    What did you mean? Sorry if I'm being thick, but I really don't see what you meant.

    Thanks again.

    Thursday, April 12, 2018 4:12 PM
  • User-1158769213 posted

    Anyone able to help here? I'm still not sure of the best way to do this.

    Thursday, May 3, 2018 3:51 PM
  • User753101303 posted

    Hi,

    It's always hard to suggest something not knowing much about the app usage (for example if it is updated in response to a customer phone call it will be different than if updates are following some other process). You load a full list (including customer details ?) when the app starts and it's really needed  ?(compared with searching just the customer you are currrently dealing with  currently ?)

    Assuming it is needed do you need to get updates as soon as possible or is it enough to get them at particular times (ie when you prepare to show a particular customer or when a search doesn't gave any results ?)

    If I start almost from the simplest thing I can think about, it would be to keep on the client side the latest "row version" for customer data. Then you could require as needed (or SignalR could sent back) all changes done after this version. If adding SignalR would it push some basic information and let the client side to decide on what is done next or would jyou push right away the whole customer data ???

    Make sure to do the simplest thing that works (and maybe reconsider if you really need to load a full list at startup ???). You do have problems with the current app design ?

    Thursday, May 3, 2018 5:58 PM
  • User-1158769213 posted

    It's always hard to suggest something not knowing much about the app usage (for example if it is updated in response to a customer phone call it will be different than if updates are following some other process). You load a full list (including customer details ?) when the app starts and it's really needed  ?(compared with searching just the customer you are currrently dealing with  currently ?)

    We currently load a full list when the app starts and filter on the client. Don't ask, that's the way it is and I can't change it! However, we don't load full customer entities, just lightweight DTOs with the bare details that are shown in the grid. When they double-click a customer in the grid, we get the full customer details from the service and show those in the details window.

    Assuming it is needed do you need to get updates as soon as possible or is it enough to get them at particular times (ie when you prepare to show a particular customer or when a search doesn't gave any results ?)

    They would like them as soon as possible.

    If I start almost from the simplest thing I can think about, it would be to keep on the client side the latest "row version" for customer data. Then you could require as needed (or SignalR could sent back) all changes done after this version. If adding SignalR would it push some basic information and let the client side to decide on what is done next or would jyou push right away the whole customer data ???

    We wouldn't push all the customer data out, only the info that's in the DTOs.

    Make sure to do the simplest thing that works (and maybe reconsider if you really need to load a full list at startup ???). You do have problems with the current app design ?

    I have a few problems with the current design, but it's too late to make any major changes now. I have to work with what is there.

    Anyway, it sounds like my original option 2 is the closest.

    Thanks for the reply.

    Thursday, May 3, 2018 7:14 PM