[C#] WCF Callback from Service

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Gertjuhjan
  • Registratie: Juli 2010
  • Laatst online: 03-09 21:26

Gertjuhjan

Software Engineer

Topicstarter
Hoi Allemaal,

Ik ben bezig voor de ontwikkeling van een service die dient als koppeling tussen twee systemen

Daar heb ik nu een testapplicatie voor gemaakt met de koppeling via een API met het systeem en aan de andere kant ben ik bezig met de ontwikkeling van de communicatie tussen de service en het tweede systeem(op dit moment een windows form als testclient).

In eerste instantie had ik dit gedaan via remoting, maar daar treedde een ander probleem op. Nu is door mijn bedrijf gevraagd om de communicatie op te zetten via WCF, maar dat was voor mij nieuw terrein.

Nu is het mij gelukt om een communicatie op te zetten tussen de service en de windows form door middel van DuplexChannelFactory<> en NetTcpBinding. Het is me ook geluk om two-way communicatie op te zetten met callbacks. (zie communicatie stroom A in het figuur)

Afbeeldingslocatie: https://dl.dropboxusercontent.com/u/23271365/Synchroon.png

Wat helaas niet werkt is communicatie stroom B. Dit is een event dat niet van origine is geinitialiseerd is vanuit de testclient en heeft dus geen callback channel.

Ik heb al geprobeerd te werken met subscribers. maar dat heeft helaas niet gewerkt. Ik heb ook al wat dingen geprobeerd met ServiceBehaviours maar dat mocht in mijn geval ook niet baten. Ook heb ik geprobeerd om een invoke te doen naar de communicatiethread.

Met logs heb ik controle gedaan hoe ver de call door de service heen loopt en ik kon zien dat het in ieder geval komt tot en met het aanroepen van de method.

Nu ben ik ondertussen desperate, want ik weet op dit moment niet waar ik naar moet zoeken.

Hebben jullie voor mij tips/pointers waar ik naar moet kijken voor een duw in de goede richting?

Xbox: Gulpener88


Acties:
  • 0 Henk 'm!

  • Guldan
  • Registratie: Juli 2002
  • Laatst online: 21-09 11:30

Guldan

Thee-Nerd

Voorzover ik weet is situatie b ook niet echt iets waarvoor duplex webservices bedoelt zijn. Is het misschien een idee om een service bus te gebruiken ipv duplex webservices. Volgens mij zoek je zoiets:

http://blogs.msdn.com/b/j...e-service-bus-part-1.aspx

Dit kan ook zonder azure draaien en dan is de source en installatie handleiding hier te vinden:

MSDN: Service Bus for Windows Server (Service Bus 1.1)

[ Voor 3% gewijzigd door Guldan op 18-12-2013 14:42 ]

You know, I used to think it was awful that life was so unfair. Then I thought, wouldn't it be much worse if life were fair, and all the terrible things that happen to us come because we actually deserve them?


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Gertjuhjan schreef op woensdag 18 december 2013 @ 14:02:
Ik heb al geprobeerd te werken met subscribers. maar dat heeft helaas niet gewerkt. Ik heb ook al wat dingen geprobeerd met ServiceBehaviours maar dat mocht in mijn geval ook niet baten. Ook heb ik geprobeerd om een invoke te doen naar de communicatiethread.
Laat eens zien wat je geprobeerd hebt dan en wat daar niet aan lukte. Want je zult inderdaad gewoon een subscribers list bij moeten hoeden. Maak een "Subscribe" method, en sla daar de callback channel op. Die callback channel kun je later weer gebruiken.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Caballeros
  • Registratie: November 2008
  • Niet online
Woy schreef op woensdag 18 december 2013 @ 15:13:
[...]

Laat eens zien wat je geprobeerd hebt dan en wat daar niet aan lukte. Want je zult inderdaad gewoon een subscribers list bij moeten hoeden. Maak een "Subscribe" method, en sla daar de callback channel op. Die callback channel kun je later weer gebruiken.
Moet ook zonder kunnen, het callback channel is al beschikbaar in de constructor van de wcf service.

Voor zover ik me kan herinneren is het wel aan te raden om met one way operation contracts te gaan werken.

[ Voor 10% gewijzigd door Caballeros op 18-12-2013 15:45 ]


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Caballeros schreef op woensdag 18 december 2013 @ 15:43:
[...]

Moet ook zonder kunnen, het callback channel is al beschikbaar in de constructor van de wcf service.
Een callback waarheen dan? Een service zonder clients heeft natuurlijk nog helemaal geen callback channels.
Caballeros schreef op woensdag 18 december 2013 @ 15:43:
[...]
Voor zover ik me kan herinneren is het wel aan te raden om met one way operation contracts te gaan werken.
Als je calls one-way gedrag hebben kun je ze logischerwijs ook zo declareren ( Geld overigens niet alleen voor je callback contract ), maar dat is puur afhankelijk van wat je precies wil berijken

[ Voor 39% gewijzigd door Woy op 18-12-2013 15:52 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • martennis
  • Registratie: Juli 2005
  • Laatst online: 07-07 10:36
Heb het niet helemaal doorgenomen, maar volgens mij moet je hier wel iets mee kunnen?
MSDN: WCF: Working with One-Way Calls, Callbacks, And Events

Acties:
  • 0 Henk 'm!

  • Caballeros
  • Registratie: November 2008
  • Niet online
Woy schreef op woensdag 18 december 2013 @ 15:51:
[...]

Een callback waarheen dan? Een service zonder clients heeft natuurlijk nog helemaal geen callback channels.
[...]

Als je calls one-way gedrag hebben kun je ze logischerwijs ook zo declareren ( Geld overigens niet alleen voor je callback contract ), maar dat is puur afhankelijk van wat je precies wil berijken
Begint nu weer te dagen, ik heb het gebruikt in per session mode en dan maakt hij netjes een instantie van je service class aan en kan je daar gelijk je callback channel oppikken. Dat is waarschijnlijk ook waar mijn problemen met two way methods vandaan kwamen.

Acties:
  • 0 Henk 'm!

  • Gertjuhjan
  • Registratie: Juli 2010
  • Laatst online: 03-09 21:26

Gertjuhjan

Software Engineer

Topicstarter
Woy schreef op woensdag 18 december 2013 @ 15:13:
[...]

Laat eens zien wat je geprobeerd hebt dan en wat daar niet aan lukte. Want je zult inderdaad gewoon een subscribers list bij moeten hoeden. Maak een "Subscribe" method, en sla daar de callback channel op. Die callback channel kun je later weer gebruiken.
De contracten:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof (IAlarmEvent))]
    public interface IAlarmServiceContract
    {
        [OperationContract]
        void AckAlarm(int UniekID);

        [OperationContract]
        void UserQuery();

        [OperationContract]
        void AlarmQuery();
        
        [OperationContract]
        void Subscribe();

        [OperationContract]
        void Unsubscribe();

        [OperationContract]
        void OnNewAlarmAdded(AlarmService.Common.Alarm alarm);
    }
    public interface IAlarmEvent
    {
        [OperationContract(IsOneWay = true)]
        void OnNewAlarm(AlarmService.Common.Alarm alarm);
    }

Vanuit de client roep ik subscribe() aan:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//Voor duidelijkheid, de methods zoals userquery en etc zijn hier in het voorbeeld er uit gehaald.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class AlarmServiceContract : IAlarmServiceContract
    {
        private static readonly List<IAlarmEvent> subscribers = new List<IAlarmEvent>(); 

        public void Subscribe()
        {

            IAlarmEvent callbackAlarmEvent = OperationContext.Current.GetCallbackChannel<IAlarmEvent>();
            if (!subscribers.Contains(callbackAlarmEvent))
            {
                subscribers.Add(callbackAlarmEvent);
            }
        }

        #endregion

        #region Unsubscribe

        public void Unsubscribe()
        {      

            IAlarmEvent callbackAlarmEvent = OperationContext.Current.GetCallbackChannel<IAlarmEvent>();
            if (subscribers.Contains(callbackAlarmEvent))
            {
                subscribers.Remove(callbackAlarmEvent);
            }
        }

        #endregion

        public void OnNewAlarmAdded(AlarmService.Common.Alarm alarm)
        {
            IAlarmEvent alarmevent = OperationContext.Current.GetCallbackChannel<IAlarmEvent>();

            alarmevent.OnNewAlarm(alarm);
        }
}


En vanuit de Service wordt het alam verzonden door:
C#:
1
2
3
4
5
public void NewAlarm(AlarmService.Common.Alarm alarm)
        {
            Action<IAlarmServiceContract> invoke = callback => callback.OnNewAlarmAdded(alarm);
            subscribers.ForEach(invoke);
}

Xbox: Gulpener88


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Daar lijkt me niks mis mee. Je zult denk toch even verder moeten debuggen. Zet WCF tracing bijvoorbeeld eens aan, dan zie je waarschijnlijk beter wat er gebeurt.

Hoe heb je de client geimplementeerd?

Je hoort natuurlijk ook nog exceptions op te vangen voor als een subscriber bijvoorbeeld al disconnected is. ( Je kan het callback object bijvoorbeeld naar ICommunicationObject casten om de status van de verbinding te controleren ).

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • Gertjuhjan
  • Registratie: Juli 2010
  • Laatst online: 03-09 21:26

Gertjuhjan

Software Engineer

Topicstarter
De client is op dit moment een Windows Form. De communicatie wordt geinitialiseerd met de volgende code:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
AlarmEvent alarmevent = new AlarmEvent();
            DuplexChannelFactory<IAlarmServiceContract> tcpFactory = new DuplexChannelFactory<IAlarmServiceContract>(alarmevent, new NetTcpBinding(SecurityMode.None), new EndpointAddress(serverip));
            tcpProxy = tcpFactory.CreateChannel();

Try
{
tcpProxy.Subscribe();
}
Catch(Exception ex)
{
Messagebox.Show(ex.ToString());
}


de class AlarmEvent : IAlarmEvent aan de client side ziet er alsvolgt uit;
C#:
1
2
3
4
5
6
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false, IncludeExceptionDetailInFaults = true)]//ConcurrencyMode.Multiple, Context = standaard op false
    public class AlarmEvent : IAlarmEvent
    {
           //Doe iets:P
}
}

Xbox: Gulpener88


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Ook daar zie ik niets geks aan, ik neem tenminste aan dat tcpFactory een instance variabele is, en dus niet stiekem gedisposed word ergens?

Je moet denk toch even naar je WCF tracing kijken ( MSDN: Configuring Tracing )

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Vedett.
  • Registratie: November 2005
  • Laatst online: 20-09 22:00
Er zijn veel meningen over WCF. Zowel positief als negatief. En ik ben eerder te plaatsen in het eerste kamp. Maar er zijn zaken die ik ronduit slecht vind en duplex channels met callbacks zijn er daar 1 van. Je gaat gegarandeert problemen krijgen met channels die gesloten worden en andere connectivity problemen zoals timeouts.

De beste oplossing is een backend schrijven die dynamisch subscriptions aanmaakt op een brokered communiatieplatform als de service bus.

Als dat niet kan zou je hier eens naar het publish-subscribe framework van IDesign moeten kijken
http://www.idesign.net/Downloads

[ Voor 11% gewijzigd door Vedett. op 20-12-2013 14:25 ]


Acties:
  • 0 Henk 'm!

  • D-Raven
  • Registratie: November 2001
  • Laatst online: 10-09 20:32
Als je richting pub sub gaat dmv een messagebus zijn daar natuurlijk nog veel meer alternatieven voor. Die wellicht nog eenvoudiger zijn ook.
Ben momenteel wel fan van RabbitMQ icm MassTransit.
Pagina: 1