locked
Need a concrete but simple/easy example of Subscribing with Generic Contracts... RRS feed

  • Question

  • I need a concrete example using 3 simple basic services...

    (A) 1 x Generic
    (B) 1 x Implementing Generic with Sub support

    (C) 1 x Subscribing to the notifications of B.

    Super simple....

    A is a datacontract assembly...
    B is a dss service that imlpements A (uses A's operation ports, state, etc etc)
    B sends notifications to all subscribers every second or something (i don't care)

    C Subscribes to B/A and receives the notifications coming from B

    I have tried over and over to get this to work but have been unsuccessful...  It's gotta be something simple...

    In every attempt, the subscribe handler on B is hit, but the subscription messages never get back out to C.
    C even gets the SubscribeResponseType fully populated with the URI's

    Please help!!

    -Richard
    Monday, February 8, 2010 7:09 PM

Answers

  • I think I got it !

    With the simulation, there is a bug sometimes where the serializer service is unable to load some types. If the issue occurs, there is a method on the serializer to manually register a type.
    I take a closer look to the code generated by our "client generation tools" and it manually register port type in the dss environment.

    Here a part of the code generated by our tools. Sorry for the syntax, is auto generated code. Receive and RegisterEvent are custom methods that actives Arbiters

    public AnalogSensorArrayClient(string service) {
                this._mainPort = Microsoft.Dss.Hosting.DssEnvironment.ServiceForwarder<Microsoft.Robotics.Services.AnalogSensorArray.Proxy.AnalogSensorOperations>(new System.Uri(service));
                this._notifyPort = new Microsoft.Robotics.Services.AnalogSensorArray.Proxy.AnalogSensorOperations();
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("LookupRequestType", Microsoft.Dss.ServiceModel.Dssp.Contract.Identifier), typeof(Microsoft.Dss.ServiceModel.Dssp.LookupRequestType));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("LookupResponse", Microsoft.Dss.ServiceModel.Dssp.Contract.Identifier), typeof(Microsoft.Dss.ServiceModel.Dssp.LookupResponse));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("Fault", W3C.Soap.Contract.Identifier), typeof(W3C.Soap.Fault));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("DropRequestType", Microsoft.Dss.ServiceModel.Dssp.Contract.Identifier), typeof(Microsoft.Dss.ServiceModel.Dssp.DropRequestType));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("DefaultDropResponseType", Microsoft.Dss.ServiceModel.Dssp.Contract.Identifier), typeof(Microsoft.Dss.ServiceModel.Dssp.DefaultDropResponseType));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("Fault", W3C.Soap.Contract.Identifier), typeof(W3C.Soap.Fault));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("GetRequestType", Microsoft.Dss.ServiceModel.Dssp.Contract.Identifier), typeof(Microsoft.Dss.ServiceModel.Dssp.GetRequestType));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("AnalogSensorArrayState", Microsoft.Robotics.Services.AnalogSensorArray.Proxy.Contract.Identifier), typeof(Microsoft.Robotics.Services.AnalogSensorArray.Proxy.AnalogSensorArrayState));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("Fault", W3C.Soap.Contract.Identifier), typeof(W3C.Soap.Fault));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("AnalogSensorArrayState", Microsoft.Robotics.Services.AnalogSensorArray.Proxy.Contract.Identifier), typeof(Microsoft.Robotics.Services.AnalogSensorArray.Proxy.AnalogSensorArrayState));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("DefaultReplaceResponseType", Microsoft.Dss.ServiceModel.Dssp.Contract.Identifier), typeof(Microsoft.Dss.ServiceModel.Dssp.DefaultReplaceResponseType));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("Fault", W3C.Soap.Contract.Identifier), typeof(W3C.Soap.Fault));
                }
                catch (System.ArgumentException ) {
                }
                Microsoft.Robotics.Services.AnalogSensorArray.Proxy.Subscribe subscribe = new Microsoft.Robotics.Services.AnalogSensorArray.Proxy.Subscribe();
                subscribe.NotificationPort = this._notifyPort;
                subscribe.NotificationShutdownPort  = this.NotifiyShutdownPort;
                this._mainPort.Post(subscribe);
                this.Receive(subscribe.ResponsePort );
                this.RegisterEvents(new Microsoft.Ccr.Core.Receiver[] {
                            Microsoft.Ccr.Core.Arbiter.Receive<Microsoft.Dss.ServiceModel.Dssp.DsspDefaultLookup>(true, this._notifyPort, this.OnDsspDefaultLookupEvent),
                            Microsoft.Ccr.Core.Arbiter.Receive<Microsoft.Dss.ServiceModel.Dssp.DsspDefaultDrop>(true, this._notifyPort, this.OnDsspDefaultDropEvent),
                            Microsoft.Ccr.Core.Arbiter.Receive<Microsoft.Robotics.Services.AnalogSensorArray.Proxy.Get>(true, this._notifyPort, this.OnGetEvent),
                            Microsoft.Ccr.Core.Arbiter.Receive<Microsoft.Dss.Core.DsspHttp.HttpGet>(true, this._notifyPort, this.OnHttpGetEvent),
                            Microsoft.Ccr.Core.Arbiter.Receive<Microsoft.Robotics.Services.AnalogSensorArray.Proxy.Replace>(true, this._notifyPort, this.OnReplaceEvent)});
            }


    Regards,
    Vincent


    http://www.simplysim.net/
    • Marked as answer by Richp582 Monday, February 22, 2010 8:15 PM
    Friday, February 19, 2010 7:37 AM
  • There is no extra initialization. RegisterEvent just adds the receiver to an interleave and Receive uses an AutoResetEvent to block the current thread until something is posted on the port.

    The RegisterTypeForSerialization method hasn't solve you problem ?

    Regards,
    Vincent
    http://www.simplysim.net/
    • Marked as answer by Richp582 Monday, February 22, 2010 8:15 PM
    Monday, February 22, 2010 8:06 AM

All replies

  • Here a sample that works :

    Generic :

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using Microsoft.Ccr.Core;
    using Microsoft.Dss.Core.Attributes;
    using Microsoft.Dss.ServiceModel.Dssp;
    using Microsoft.Dss.ServiceModel.DsspServiceBase;
    using W3C.Soap;
    
    namespace Generic
    {
        public sealed class Contract
        {
            [DataMember]
            public const string Identifier = "http://test.org/2010/02/generic.html";
        }
    
        [DataContract]
        public class GenericState
        {
            [DataMember]
            public int Test { get; set; }
        }
    
        [ServicePort]
        public class GenericOperations : PortSet<DsspDefaultLookup, DsspDefaultDrop, Get, Replace, Subscribe>
        {
        }
    
        public class Get : Get<GetRequestType, PortSet<GenericState, Fault>>
        {
            public Get() { }
            public Get(GetRequestType body) : base(body) { }
            public Get(GetRequestType body, PortSet<GenericState, Fault> responsePort) : base(body, responsePort) { }
        }
    
        public class Replace : Replace<GenericState, PortSet<DefaultReplaceResponseType, Fault>>
        {
            public Replace() { }
            public Replace(GenericState body) : base(body) { }
            public Replace(GenericState body, PortSet<DefaultReplaceResponseType, Fault> responsePort) : base(body, responsePort) { }
        }
    
        public class Subscribe : Subscribe<SubscribeRequestType, PortSet<SubscribeResponseType, Fault>>
        {
            public Subscribe() { }
            public Subscribe(SubscribeRequestType body) : base(body) { }
            public Subscribe(SubscribeRequestType body, PortSet<SubscribeResponseType, Fault> responsePort) : base(body, responsePort) { }
        }
    }
    
    
    



    Implementation :

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using Microsoft.Ccr.Core;
    using Microsoft.Dss.Core.Attributes;
    using Microsoft.Dss.ServiceModel.Dssp;
    using Microsoft.Dss.ServiceModel.DsspServiceBase;
    using W3C.Soap;
    using submgr = Microsoft.Dss.Services.SubscriptionManager;
    using generic = Generic.Proxy;
    
    namespace Implementation
    {
        public sealed class Contract
        {
            [DataMember]
            public const string Identifier = "http://test.org/2010/02/implementation.html";
        }
    
        [Contract(Contract.Identifier)]
        [DisplayName("Implementation")]
        [Description("Implementation service (no description provided)")]
        [AlternateContract(generic.Contract.Identifier)]
        class ImplementationService : DsspServiceBase
        {
            [ServiceState]
            generic.GenericState _state = new generic.GenericState();
    
            [ServicePort("/Implementation", AllowMultipleInstances = true)]
            generic.GenericOperations _mainPort = new generic.GenericOperations();
    
            [SubscriptionManagerPartner]
            submgr.SubscriptionManagerPort _submgrPort = new submgr.SubscriptionManagerPort();
    
            public ImplementationService(DsspServiceCreationPort creationPort)
                : base(creationPort)
            {
            }
    
            protected override void Start()
            {
                _state.Test = 0;
                base.Start();
            }
    
            [ServiceHandler(ServiceHandlerBehavior.Concurrent)]
            public void GetHandler(generic.Get get)
            {
                get.ResponsePort.Post(_state);
            }
    
            [ServiceHandler(ServiceHandlerBehavior.Exclusive, Interval = 1)]
            public void ReplaceHandler(generic.Replace replace)
            {
                replace.ResponsePort.Post(DefaultReplaceResponseType.Instance);
                SendNotification<generic.Replace>(_submgrPort, replace);
            }
    
            [ServiceHandler]
            public void SubscribeHandler(generic.Subscribe subscribe)
            {
                SubscribeHelper(_submgrPort, subscribe, subscribe.ResponsePort);
            }
        }
    }
    
    
    


    Test :

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using Microsoft.Ccr.Core;
    using Microsoft.Dss.Core.Attributes;
    using Microsoft.Dss.ServiceModel.Dssp;
    using Microsoft.Dss.ServiceModel.DsspServiceBase;
    using W3C.Soap;
    using Microsoft.Dss.Core;
    using generic = Generic.Proxy;
    
    namespace Observer
    {
        public sealed class Contract
        {
            [DataMember]
            public const string Identifier = "http://test.org/2010/02/observer.html";
        }
    
        [ServicePort]
        public class ObserverOperations : PortSet<DsspDefaultLookup, DsspDefaultDrop>
        {
        }
    
    
        [Contract(Contract.Identifier)]
        [DisplayName("Observer")]
        [Description("Observer service (no description provided)")]
        class ObserverService : DsspServiceBase
        {
            [ServicePort("/Observer", AllowMultipleInstances = true)]
            ObserverOperations _mainPort = new ObserverOperations();
    
            [Partner("Generic", Contract = generic.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.UsePartnerListEntry)]
            generic.GenericOperations _genericPort = new generic.GenericOperations();
            generic.GenericOperations _genericNotify = new generic.GenericOperations();
    
            public ObserverService(DsspServiceCreationPort creationPort)
                : base(creationPort)
            {
            }
    
            protected override void Start()
            {
                base.Start();
    
                Activate(Arbiter.Receive<generic.Replace>(true, _genericNotify, (e) => LogInfo(LogGroups.Console, "Notification received !")));
                _genericPort.Subscribe(_genericNotify, typeof(generic.Replace));
            }
        }
    }
    
    
    


    Manifest :

    <?xml version="1.0"?>
    <Manifest xmlns:observer="http://test.org/2010/02/observer.html" 
              xmlns:implementation="http://test.org/2010/02/implementation.html" 
              xmlns:this="urn:uuid:e9f5cad5-7dbb-4deb-9447-0affad996255" 
              xmlns:dssp="http://schemas.microsoft.com/xw/2004/10/dssp.html" 
              xmlns="http://schemas.microsoft.com/xw/2004/10/manifest.html">
      <CreateServiceList>
        <ServiceRecordType>
          <dssp:Contract>http://test.org/2010/02/observer.html</dssp:Contract>
          <dssp:PartnerList>
            <dssp:Partner>
              <dssp:Contract>http://test.org/2010/02/generic.html</dssp:Contract>
              <dssp:PartnerList />
              <dssp:Name>observer:Generic</dssp:Name>
              <dssp:ServiceName>this:Implementation</dssp:ServiceName>
            </dssp:Partner>
          </dssp:PartnerList>
          <Name>this:Observer</Name>
        </ServiceRecordType>
        <ServiceRecordType>
          <dssp:Contract>http://test.org/2010/02/implementation.html</dssp:Contract>
          <dssp:PartnerList />
          <Name>this:Implementation</Name>
        </ServiceRecordType>
      </CreateServiceList>
    </Manifest>



    Regards,
    Vincent








    http://www.simplysim.net/
    Tuesday, February 9, 2010 7:34 AM
  • Awesome, thank you so much... 2 questions for you though.

    1.) In the Observer you reference the generic proxy, not the implementation, previously I would use the contract of the implementation against the generic operations.

    2.) It looks like you are relying on a manifest file.  Would there be another approach to this that does NOT need a manifest file.

    The reason I ask about the manifest is because... one, we are not using manifests right now (everything is just running inside one host, and we have a custom host module.  And two, because our client is going to be using service forwarders to communicate with the DSS Services on the back end, we the client won't even have any manifests.

    Thanks for all of the help!

    -Rich
    Tuesday, February 9, 2010 1:33 PM
  • Without manifest, there are two ways :
    - using a Create partner policy
    - using code / request to constructor service

    The first approach seems useless because you need to reference the implementation and not the generic proxy, and it's break genericty (there is no longer need to define a generic contract)

    For the second approach you have to issue request to Constructor/Manifest loader services or use DssEnvironment methods in order to specify relationship between the observer and the implementation. But in some way, it's break a little the genericity since you will have to recompile the "loader" module the day you change the implementation. With a manifest, you could change the implementation just by editing an XML file.

    Regards,
    Vincent


    http://www.simplysim.net/
    Wednesday, February 10, 2010 7:45 AM
  • Would there be any chance you could give an example of the second method, or at least explain in more detail?

    Our host does use the DssEnvironment.dll and we understand that it is going to be bound to the definition of the generic contract...

    However, we are pretty set on using service forwards to connect to the already running services on another host, so figuring out away to accomplish that would be the goal.

    Thanks,
    Richard
    Thursday, February 11, 2010 7:26 PM
  • DssEnvironment provides static methods "CreateService" that accept an argument of type ServiceInfoType. You could also post a request to the constructor service.
    ServiceInfoType matches basically a manifest. The step to fill it are :

    - Create a new instance of ServiceInfoType with your Observer contract as parameters
    - Create an instance of PartnerType with
     XmlQualifiedName name => name of the partner in observer service (in my example, it's "Generic" with observer contract uri as namespace
    string contract => generic contract
    string service => URL to the implementation service
    - Create a new List<PartnerType> with the previously created one
    - Set the PartnerList property on the service info type

    When you will send this request to constructor service (by calling DssEnvironment.CreateService), it will bind the implementation to the newly created observer service.

    Regards,
    Vincent


    http://www.simplysim.net/
    Friday, February 12, 2010 7:51 AM
  • I think I am on the right track, what you have shown me so far has been helpful, but I think we have a small miscommunication...

    What I want is for me to be able to subscribe to the Implementation inside of my DssEnvironment...  I don't need the constructor service because the Impl service is already running.

    the Observer is actually the client, and the client does not have any Dss Nodes... just service forwarders... but I think I see what your trying to do here... so I will mess around with it.

    I am not sure what would be the XmlQualifiedName in my case...

    Thanks for all of the help so far, its been great...

    Here is my load service task 
    When the the directory port returns my service the partnerlist have 5 partners, including a sub mgr... do I need to create a forwarder to that guy too?

    Edit: I tried creating a serviceforwarder to the AlternateContract_0 port on the Service PartnerList, but it still doesn't work.... humm...

    Thanks,
    Rich

            private IEnumerator<ITask> LoadService()
            {
                DirectoryPort remoteDir = DssEnvironment.ServiceForwarder<DirectoryPort>(
                    new Uri(string.Format("http://{0}/{1}",
                                          ConfigurationManager.AppSettings["remotedss"],
                                          "directory")));
    
                var serviceInfo = new ServiceInfoType(_contractId);
                var reqBody = new ds.QueryRequest() {QueryRecord = serviceInfo};
                var query = new ds.Query(reqBody);
    
                remoteDir.Post(query);
    
                yield return Arbiter.Choice(
                    query.ResponsePort,
                    delegate(ds.QueryResponse success)
                    {
                        if (success.RecordList != null)
                        {
                            var addr = new System.Uri(success.RecordList[0].Service);
    
                            _mainPort = DssEnvironment.ServiceForwarder<generic.GenericOperations>(addr);
                            Console.WriteLine("Found Service!");
                        }
                    },
                    delegate(W3C.Soap.Fault failure)
                    {
                        Console.WriteLine(string.Format("Failed to Find Service: {0}", failure));
                    });
    
                signal.Set();
            }

    -Rich
    Friday, February 12, 2010 8:14 PM
  • The generic URL should be something like "implementationURL/genericportname". Do the AlternateContrat_0 contains something like that ?

    But I guess the real problem is that the Observer isn't a service (as you say, "no Dss nodes, just forwarders"). When a service subscribe to another, it creates a notification port and sends an "notification" URL to the publisher service. The publisher service just relay the request to the subscription manager. I suppose that when the subscription manager must send a notification to an observer, it creates a forwarder to this notification URL. Since you only use forwarders, maybe there is a problem with this notification port/url. Maybe you should post your subscription code.
    At SimplySim, we have made some kind of "proxy generator", that generates assemblies for remote communication with a service based on forwarders. As far as we know, it works with subscription.

    Regards,
    Vincent


    http://www.simplysim.net/
    Monday, February 15, 2010 8:13 AM
  • The client lives on port: 40000
    The server lives on port: 60000

    What I am doing in my service forwarder is creating three ports...
    All ports are of type GenericOperations (Defined in the generic dss contract)

    The first port, mainPort is: dssp.tcp://localhost:60001/dssevent
    The second port, genPort is: dssp.tcp://localhost:60001/dssevent/genericdsscontract
    The last port, is the notifyPort and is just a new GenericOperations

    When I subscribe the server gets the request and what appears to be a valid subscriber uri:
    New Subscriber: dssp.tcp://localhost:40001/dssenvironment/61cb6613-7efd-4f9d-a9aa-5f02d43b21bd/dss/notificationtarget/850016d6-395e-4b49-8029-ce0cc4de146e

    I should also note, that the server successfully responds to my subscribe request, and the msg "Subscription Request Completed!" appears!

    When I receive a message, I want to place the data in a new port and raise an event...  Neither ever happen...

    I have also tried:
    Doing mainPort.Subscribe too but that doesn't work either....

    Again, thanks for all of the help!!

    My client subscription code looks like this:
            private void SubscribeToService()
            {
                _notifyPort = new GenericOperations();
                var subs = new generic.Subscribe {NotificationPort = _notifyPort};
                _genPort.Post(subs);
    
                Console.WriteLine("Attempting to Subscribe...");
                Arbiter.Activate(
                    _dispatcherQueue,
                    Arbiter.Choice(subs.ResponsePort,
                                   delegate(SubscribeResponseType subscribeResponseType)
                                       { Console.WriteLine("Subscription Request Completed!"); },
                                   delegate(Fault fault)
                                       { Console.WriteLine(string.Format("Subscription Failed! {0}", fault)); }
                        ));
                
                Arbiter.Activate(_dispatcherQueue,
                                         Arbiter.Receive<Deltas>(
                                             true, _notifyPort, deltas =>
                                                 { 
                                                     DeltasPort.Post(deltas.Body);
                                                     IncomingDeltas(null, null);
                                                 }
                                                 ));
            }
    Thanks,
    Richard P.
    Tuesday, February 16, 2010 3:24 PM
  • In the server side, are you sure the notifications are correctly sent ?
    Do you use a firewall or a security software that could block the notifications ?

    Regards,
    Vincent
    http://www.simplysim.net/
    Wednesday, February 17, 2010 7:41 AM
  • Yea, if I remove the generics it works.  Both client and server are on the same host, no firewall, and I have disabled the Dss security.

    It almost feels like like the handler never wakes up or gets fired...

    I don't know why it doesn't work, kinda of out of ideas... I really thought using the generic partnership was going to make it work lol... but idk.

    You said you are doing something similar like this and it works?
    I also saw a post on the forums where someone said you needed to boot the subscription manager to make it work...

    But like I said when using the generics, I could do send and response messages, it was always just the subscriptions that failed...

    Any other ideas?

    Thanks so much for the help!
    -Rich



    Wednesday, February 17, 2010 12:38 PM
  • I am getting ooohhh so close...

    I changed my host to use a manifest generated by the M.E.
    I have my Client Service that needs a Generic that is fullfilled by my Implementation service

    The problem now, is I am getting the following error message

    *** "TaskExecutionWorker:HandleException": Exception:System.NotSupportedException: Proxy type not found for outbound request or response. Make sure you have compiled a proxy and transform dll for the target service.Outbound type:MyApp.Server.Services.Common.GenericDssContract.Proxy.DeltasCollections
       at Microsoft.Dss.Services.Serializer.DataCache.GetQualifiedName(Type t)
       at Microsoft.Dss.Services.SubscriptionManager.SubscriptionManagerCommon.ForwardNotification(Submit req)
       at Microsoft.Ccr.Core.Task`1.Execute()
       at Microsoft.Ccr.Core.TaskExecutionWorker.ExecuteTaskHelper(ITask currentTask)
       at Microsoft.Ccr.Core.TaskExecutionWorker.ExecuteTask(ITask& currentTask, DispatcherQueue p, Boolean bypassExecute)
       at Microsoft.Ccr.Core.TaskExecutionWorker.ExecutionLoop()

    This error message comes up everytime my Implementation does a SendNotification...

    Both the "observer" and the implementation are referencing the same proxy dll.

    Any ideas?

    Also, here is the code for defining the DeltasCollection
        public class Deltas : Update<DeltaCollections, PortSet<DefaultUpdateResponseType, Fault>>
        {
        }
    
        [DataContract]
        [DataMemberConstructor]
        public class DeltaCollections
        {
            [DataMember]
            public string DeltaType;
            [DataMember]
            public DateTime TimeStamp;
    
            //[DataMember] 
            //public List<IServerEntity> Inserts;
            //[DataMember]
            //public List<IServerEntity> Updates;
            //[DataMember]
            //public List<uint> Deletes;
        }
    


    Thanks,
    Rich

    Wednesday, February 17, 2010 10:15 PM
  • I think I got it !

    With the simulation, there is a bug sometimes where the serializer service is unable to load some types. If the issue occurs, there is a method on the serializer to manually register a type.
    I take a closer look to the code generated by our "client generation tools" and it manually register port type in the dss environment.

    Here a part of the code generated by our tools. Sorry for the syntax, is auto generated code. Receive and RegisterEvent are custom methods that actives Arbiters

    public AnalogSensorArrayClient(string service) {
                this._mainPort = Microsoft.Dss.Hosting.DssEnvironment.ServiceForwarder<Microsoft.Robotics.Services.AnalogSensorArray.Proxy.AnalogSensorOperations>(new System.Uri(service));
                this._notifyPort = new Microsoft.Robotics.Services.AnalogSensorArray.Proxy.AnalogSensorOperations();
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("LookupRequestType", Microsoft.Dss.ServiceModel.Dssp.Contract.Identifier), typeof(Microsoft.Dss.ServiceModel.Dssp.LookupRequestType));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("LookupResponse", Microsoft.Dss.ServiceModel.Dssp.Contract.Identifier), typeof(Microsoft.Dss.ServiceModel.Dssp.LookupResponse));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("Fault", W3C.Soap.Contract.Identifier), typeof(W3C.Soap.Fault));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("DropRequestType", Microsoft.Dss.ServiceModel.Dssp.Contract.Identifier), typeof(Microsoft.Dss.ServiceModel.Dssp.DropRequestType));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("DefaultDropResponseType", Microsoft.Dss.ServiceModel.Dssp.Contract.Identifier), typeof(Microsoft.Dss.ServiceModel.Dssp.DefaultDropResponseType));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("Fault", W3C.Soap.Contract.Identifier), typeof(W3C.Soap.Fault));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("GetRequestType", Microsoft.Dss.ServiceModel.Dssp.Contract.Identifier), typeof(Microsoft.Dss.ServiceModel.Dssp.GetRequestType));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("AnalogSensorArrayState", Microsoft.Robotics.Services.AnalogSensorArray.Proxy.Contract.Identifier), typeof(Microsoft.Robotics.Services.AnalogSensorArray.Proxy.AnalogSensorArrayState));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("Fault", W3C.Soap.Contract.Identifier), typeof(W3C.Soap.Fault));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("AnalogSensorArrayState", Microsoft.Robotics.Services.AnalogSensorArray.Proxy.Contract.Identifier), typeof(Microsoft.Robotics.Services.AnalogSensorArray.Proxy.AnalogSensorArrayState));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("DefaultReplaceResponseType", Microsoft.Dss.ServiceModel.Dssp.Contract.Identifier), typeof(Microsoft.Dss.ServiceModel.Dssp.DefaultReplaceResponseType));
                }
                catch (System.ArgumentException ) {
                }
                try {
                    Microsoft.Dss.Hosting.DssEnvironment.RegisterTypeForSerialization(new System.Xml.XmlQualifiedName("Fault", W3C.Soap.Contract.Identifier), typeof(W3C.Soap.Fault));
                }
                catch (System.ArgumentException ) {
                }
                Microsoft.Robotics.Services.AnalogSensorArray.Proxy.Subscribe subscribe = new Microsoft.Robotics.Services.AnalogSensorArray.Proxy.Subscribe();
                subscribe.NotificationPort = this._notifyPort;
                subscribe.NotificationShutdownPort  = this.NotifiyShutdownPort;
                this._mainPort.Post(subscribe);
                this.Receive(subscribe.ResponsePort );
                this.RegisterEvents(new Microsoft.Ccr.Core.Receiver[] {
                            Microsoft.Ccr.Core.Arbiter.Receive<Microsoft.Dss.ServiceModel.Dssp.DsspDefaultLookup>(true, this._notifyPort, this.OnDsspDefaultLookupEvent),
                            Microsoft.Ccr.Core.Arbiter.Receive<Microsoft.Dss.ServiceModel.Dssp.DsspDefaultDrop>(true, this._notifyPort, this.OnDsspDefaultDropEvent),
                            Microsoft.Ccr.Core.Arbiter.Receive<Microsoft.Robotics.Services.AnalogSensorArray.Proxy.Get>(true, this._notifyPort, this.OnGetEvent),
                            Microsoft.Ccr.Core.Arbiter.Receive<Microsoft.Dss.Core.DsspHttp.HttpGet>(true, this._notifyPort, this.OnHttpGetEvent),
                            Microsoft.Ccr.Core.Arbiter.Receive<Microsoft.Robotics.Services.AnalogSensorArray.Proxy.Replace>(true, this._notifyPort, this.OnReplaceEvent)});
            }


    Regards,
    Vincent


    http://www.simplysim.net/
    • Marked as answer by Richp582 Monday, February 22, 2010 8:15 PM
    Friday, February 19, 2010 7:37 AM
  • Looks very interesting...

    What is your "this.Receive" and your "this.RegisterEvents"

    Thanks for the help, I think we are getting ever so close!

    -Richard
    Friday, February 19, 2010 1:14 PM
  • Receive and RegisterEvents are defined in the parent class. It does some CCR stuff but with a single thread way.
    http://www.simplysim.net/
    Friday, February 19, 2010 6:34 PM
  • Yea, but what do they do?

    Especially the RegisterEvents?

    Are they doing anything else?  Perhaps some extra initialization!

    Thanks,
    Richard
    Friday, February 19, 2010 7:14 PM
  • There is no extra initialization. RegisterEvent just adds the receiver to an interleave and Receive uses an AutoResetEvent to block the current thread until something is posted on the port.

    The RegisterTypeForSerialization method hasn't solve you problem ?

    Regards,
    Vincent
    http://www.simplysim.net/
    • Marked as answer by Richp582 Monday, February 22, 2010 8:15 PM
    Monday, February 22, 2010 8:06 AM
  • It HAS!!  I cannot believe it!!

    Thank you, Thank you, Thank you!!!

    Your the man!

    -Rich
    Monday, February 22, 2010 12:33 PM