1

I have an operation contract in my service contract called

Schedule[] GetScheduleObjects();

I have a datameber in that operation contract called "Tasks" that returns a list of sub objects.

[DataMember()]
public Task[] Tasks

The issues is when the operation contract is called the method executes but the "get" of "Tasks" occurs twice. The first time it contains valid runtime instances, the second time it is null which causes a serialization exception. This happens despite only one call to the service. The binding is a tcp connection using a duplex proxy. Ideas?????

The Datacontract

[DataContract()]
public class Schedule
{
    public Schedule(string name)
    {
        this.Name = name;
    }

    [DataMember()]
    public string Name { get; private set; }

    [DataMember()]
    public bool Running { get; set; }

    /// <summary>
    /// Schedule Task is a DataMember object, do not modify
    /// </summary>
    [DataMember()]
    public Task[] Tasks
    {
        get { return _Tasks.ToArray(); }
    }

    private List<Task> _Tasks = new List<Task>();

     ///<summary>
     /// Use this property to add objects 
     ///</summary>
    public List<Task> ScheduleTasks 
    {
        get { return _Tasks; }
    }
}

The service contract

[ServiceContract(CallbackContract = typeof(ISummitDashboardCallbackContract))]
public interface ISchedulerContract : ISummitDashboardContract
{
    /// <summary>
    /// Sets the named schedule into "run" mode
    /// </summary>
    /// <param name="scheduleName"></param>
    /// <returns></returns>
    [OperationContract()]
    void StartSchedule(string scheduleName);

    /// <summary>
    /// Pauses the currently running schedule
    /// </summary>
    /// <param name="scheduleName"></param>
    [OperationContract()]
    void PauseSchedule(string scheduleName);

    /// <summary>
    /// Removes the named schedule from "run" mode
    /// </summary>
    /// <param name="scheduleName"></param>
    /// <returns></returns>
    [OperationContract()]
    void StopSchedule(string scheduleName);

    /// <summary>
    /// Flips the "active" state of the task with the named id
    /// </summary>
    /// <param name="scheduleName"></param>
    /// <param name="Id"></param>
    [OperationContract()]
    void ToggleTaskState(string scheduleName, string Id);

    /// <summary>
    /// Flips the "active" state of the action with the named id
    /// </summary>
    /// <param name="scheduleName"></param>
    /// <param name="Id"></param>
    /// <returns></returns>
    [OperationContract()]
    void ToggleActionState(string scheduleName, string Id);

    /// <summary>
    /// Returns the information to build the tree list in the dashboard
    /// </summary>
    /// <returns></returns>
    [OperationContract()]
    Schedule[] GetScheduleObjects();

    /// <summary>
    /// Returns the events of the scheduler
    /// </summary>
    /// <returns></returns>
    [OperationContract()]
    SchedulerEvent[] GetSchedulerEvents(int startIndex, int count, int eventLogEntryType);

}
fanuc_bob
  • 857
  • 1
  • 7
  • 20

1 Answers1

0

You'll need to add a setter to property Tasks, and you'll also need to increase the visibility of Name to at least protected - WCF will need to use these in order to deserialize objects of this class.

As a secondary issue, if a client generates a proxy (e.g. with Add Service Reference or via SvcUtil.exe), the 'code behind' Tasks (i.e. return _Tasks.ToArray(); which is coupled to ScheduledTasks) will be lost, and the client will instead just get a simple automatic backing property to property Tasks (with the collection class selected during the proxy generation). This second issue won't however happen however if you share type.

Community
  • 1
  • 1
StuartLC
  • 104,537
  • 17
  • 209
  • 285