-1

I have implemented a data contract which is successfully deserialized by the WCF test client. Now, how can I do this in a custom client I have made?

The contract I have is this:

[ServiceContract]
[ServiceKnownType(typeof(List<StageContract>))]
public interface IUserService
{
    [OperationContract]
    void CreateUser(string name, string pwd, bool admin);

    [OperationContract]
    bool LogInUser(string name, string pwd);

    [OperationContract]
    List<StageContract> getAllStages();


[DataContract]
public class StageContract
{
    private int _stageID;
    private int _projectID;
    private int _wip;
    private string _name;
    private int _position;

    public StageContract(Stage s)
    {
        StageID = s.ID;
        ProjectID = s.ProjectID;
        WIP = s.WIP;
        Name = s.Name;
        Position = s.Position;
    }

    [DataMember]
    int StageID
    {
        get { return _stageID; }
        set { _stageID = value; }
    }

    [DataMember]
    int ProjectID
    {
        get { return _projectID; }
        set { _projectID = value; }
    }

    [DataMember]
    int WIP
    {
        get { return _wip; }
        set { _wip = value; }
    }

    [DataMember]
    string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    [DataMember]
    int Position
    {
        get { return _position; }
        set { _position = value; }
    }
}
}

The service class has the following:

    public List<StageContract> getAllStages() 
    {
            return (new StageController())
           .getAllStages()
           .Values
           .Select(s => new StageContract(s))
           .ToList();
    }

In the client side:

using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using KanbanProject.ServiceReference1;

public partial class MainWindow : Window
{
    public MainWindow()
    {

        InitializeComponent();
        this.Loaded += new RoutedEventHandler(MainWindow_Loaded);

    }

    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        var client = new UserServiceClient();
        List<StageContract> myList = client.getAllStages();
    }

At execution I encounter the following error:

An unhandled exception of type 'System.ServiceModel.Dispatcher.NetDispatcherFaultException' 
occurred in mscorlib.dll

Additional information: The formatter 
threw an exception while trying to deserialize 
the message: There was an error while trying to 
deserialize parameter http://tempuri.org/:getAllStagesResult. 
The InnerException message was 'Element getAllStagesResult from 
namespace http://tempuri.org/ cannot have child contents to be 
deserialized as an object. Please use XmlNode[] to deserialize 
this pattern of XML.'.  Please see InnerException for more details.

I tried looking into XmlNode[] usage: http://geekswithblogs.net/TimH/archive/2006/02/09/68857.aspx

Also this: WCF: Serializing and Deserializing generic collections

This: WCF. IList is deserialized as array. How to make it be any writable list (ArrayList)?

And this: WCF/RESTful DataContract deserialization issue

Thank you in advance!

*UPDATE: After finally deserializing on the client side I encountered the following:

For List<StageContract> myList = client.getAllStages(); I have Cannot implicitly convert type "object" to "System.Colections.Generic.List<StageContract>" An explicit conversion exists(are you missing a cast?).

*SOLVED: answer posted below.

Community
  • 1
  • 1
graiul
  • 21
  • 7
  • @jstreet I tried this and it does not work, the client does not know about the StageContract type, rathr it seems it receives an object of type Object. It keeps saying it is a problem with the deserializing formatter and suggesting I use XmlNode[]. – graiul May 03 '16 at 10:36
  • @jstreet I did, but it renders it unusable. I reconfigured the service reference to return System.Collections.Generic.List. Tried to cast, it does not work yet. – graiul May 03 '16 at 10:59
  • @jstreet I posted the MCVE of the service. – graiul May 03 '16 at 11:15
  • @jstreet Maybe the ServiceKnownType is not transfered to the client properly? Or either I am yet to properly configure the client to see it? – graiul May 03 '16 at 11:17
  • @jstreet It's a client made in WPF. Sorry I forgot to mention it. I have some XAML controls that I am trying to populate. – graiul May 03 '16 at 11:25
  • @jstreet I added the MCVE for the client. Altough I have a ViewModel attached which contains code to which the main window XAML controls would be bound to. I hope this makes sense. – graiul May 03 '16 at 11:38
  • @jstreet Ok, I am trying not to get things mixed up so here goes: the main window has no other functionality other than the InitializeComponent() method. On the XAML side it contains my controls which are bound to another class named MainVewModel. I have moved the deserialization instructions there because I need the transferred data to copied into a few lists that will be reprezented in the GUI. There is no Load handler in either of these classes. Updating MCVE. – graiul May 03 '16 at 12:00
  • @jstreet I updated the question. I wrote the Load event handler myself since it was not existent. Still does not recognize StageContract. I hope I am following your instructions correctly. – graiul May 03 '16 at 12:18
  • @jstreet For `List myList = client.getAllStages();` I have `Cannot implicitly convert type "object" to "System.Colections.Generic.List" An explicit conversion exists(are you missing a cast?)`. – graiul May 03 '16 at 12:36
  • @jstreet Solved it: the problem was the ServiceReference configuration collection type. Even though I changed it befor to System.Collections.Generic.List I left the `Always generate message contracts` ticked which in turn did not let for some reason the StageContract type to be recognized. Thank you so much for your time!! – graiul May 03 '16 at 12:59
  • @jstreet I am kinda new to this site and its reputation system. How can I put some your way? – graiul May 03 '16 at 13:08

2 Answers2

1

Change [ServiceKnownType(typeof(List<StageContract>))] to [ServiceKnownType(typeof(StageContract))]. You never have to identify List<T>...only T. In your case, T is still not in KnownTypes.

Clay
  • 4,999
  • 1
  • 28
  • 45
  • Thank you for your help! I want to upvote your answer but the site says I don't have enough rep yet. I think I managed to solve the problem before your answer; I have posted the solution in a separate answer. – graiul May 03 '16 at 20:54
1

Solved it: the problem was the ServiceReference configuration collection type. Even though I changed it before to System.Collections.Generic.List I left the Always generate message contracts ticked which in turn did not let for some reason the StageContract type to be recognized.

Thank you @jstreet and @Clay!

graiul
  • 21
  • 7