0

I'm trying to get a reference type from a WCF service with Xamarin.Forms but I get an exception when I get the data back from the server.

System.Runtime.Serialization.SerializationException: Error in line 1 position 326. Element 'http://tempuri.orgtGetRecordResult' contains data of the 'http://schemas.datacontract.org/2004/07/Adapt.Model.Security:User' data contract. The deserializer has no knowledge of any type that maps to this contract.

My Code

[KnownType(typeof(User))]
public partial class DataAccessServiceClient : ClientBase<IDataAccessService>, IDataAccessService, IServiceClient
{
    public DataAccessServiceClient(Binding binding, EndpointAddress endpointAddress) : base(binding, endpointAddress)
    {

    }

    public virtual async Task OpenAsync()
    {
        await Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndOpen));
    }

    public virtual Task CloseAsync()
    {
        return Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginClose(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndClose));
    }

    public string Authenticate(string username, string password)
    {
        return Channel.Authenticate(username, password);
    }

    public IRecord GetRecord(string ObjectTypeName, object primaryKeyValue, ConnectionInfo connectionInfo)
    {
        return Channel.GetRecord(ObjectTypeName, primaryKeyValue, connectionInfo);
    }
}

[ServiceContract()]
public interface IDataAccessService
{
    [OperationContract()]
    string Authenticate(string username, string password);

    [OperationContract()]
    IRecord GetRecord(string ObjectTypeName, object primaryKeyValue, ConnectionInfo connectionInfo);

}

public static async Task<IDataAccessService> GetDataAccessServiceProxy()
{
    var binding = GetBinding();
    var proxy = new DataAccessServiceClient(binding, new EndpointAddress($"http://10.0.2.152/helpdeskservices/DataAccessService.svc"));
    await proxy.OpenAsync();
    return proxy;
}

private async Task DisplayTask()
{
    try
    {
        var proxy = await App.GetDataAccessServiceProxy();
        var record = proxy.GetRecord(typeof(User).FullName, 1, new Adapt.Model.Data.ConnectionInfo { AuthToken = _AuthToken });
        await DisplayAlert("info", "user details = " + (record as User)?.UserName, "test complete");
    }
    catch (Exception ex)
    {
        await DisplayAlert("error", ex.ToString() + "\n\n\n" + ex.InnerException?.ToString() ?? "No inner exception", "retry");
        await DisplayTask();
    }
}

Calling Authenticate works fine, I'm assuming because it's a value type but getting the User object has this issue.

The Pademelon
  • 656
  • 9
  • 25

1 Answers1

1

You cannot use object as type of one of the arguments in GetRecord (look also at this SO question). So you have to change your GetRecord contract. One option is to define a base class for all the types you have to use and use that class in GetRecord. Then you put the KnownType declaration on that base class for all the derived classes. Look at this for an example using Person (base class) and Student/Teacher (derived class). You have the same problem with the return value IRecord. At some point you have to tell WCF how to serialize/deserialize the object represented by IRecord. See this SO question how to add KnownType's dynamically.

Community
  • 1
  • 1
Jeroen Heier
  • 3,003
  • 14
  • 27
  • 31
  • So the KnownTypeAttribute goes on the User class? I'm sorry, I'm really unfamiliar with the structure of WCF Technology. Could you explain further? – The Pademelon Jun 03 '16 at 07:08
  • I tried setting the KnownType to IRecord which is an interface shared by all records in the system. The server threw an error saying something like "System.Object" is already a KnownType so I can't add IRecord. The WCF service already communicates with a silverlight app and a UWP app so there's nothing wrong with what's on the server. I just don't understand what I'm doing wrong. – The Pademelon Jun 03 '16 at 08:02
  • Ah, I understand now. I need to put the KnownType attribute on the base class with the types that derive from that class as the parameter for the attribute. But the problem with that is that the projects are structured so that the base class is separate from the derived classes so as a result I can't reference the derived classes from the scope of the base class. How do I add the attribute in this situation? – The Pademelon Jun 05 '16 at 23:11