【问题标题】:KnownTypeAttribute Defined on Service Client But Still Has No Knowledge of TypeKnownTypeAttribute 在服务客户端上定义但仍然不知道类型
【发布时间】:2016-06-03 06:49:50
【问题描述】:

我正在尝试使用 Xamarin.Forms 从 WCF 服务获取引用类型,但是当我从服务器获取数据时出现异常。

System.Runtime.Serialization.SerializationException:第 1 行位置 326 出错。元素“http://tempuri.orgtGetRecordResult”包含“http://schemas.datacontract.org/2004/07/Adapt.Model.Security:User”数据协定的数据。反序列化器不知道任何映射到该合约的类型。

我的代码

[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();
    }
}

调用 Authenticate 工作正常,我假设是因为它是一个值类型,但获取 User 对象有这个问题。

【问题讨论】:

    标签: c# wcf xamarin.forms


    【解决方案1】:

    您不能将对象用作 GetRecord 中的参数之一(另请参阅this SO 问题)。所以你必须改变你的 GetRecord 合同。一种选择是为您必须使用的所有类型定义一个基类,并在 GetRecord 中使用该类。然后将 KnownType 声明放在所有派生类的该基类上。查看 this 以获取使用 Person(基类)和 Student/Teacher(派生类)的示例。您对返回值 IRecord 有同样的问题。在某些时候,您必须告诉 WCF 如何序列化/反序列化由 IRecord 表示的对象。请参阅this SO question how to add KnownType's dynamic。

    【讨论】:

    • 那么 KnownTypeAttribute 在 User 类上?对不起,我对WCF技术的结构真的不熟悉。你能进一步解释一下吗?
    • 我尝试将 KnownType 设置为 IRecord,这是系统中所有记录共享的接口。服务器抛出一个错误,说“System.Object”之类的东西已经是 KnownType,所以我不能添加 IRecord。 WCF 服务已经与 silverlight 应用程序和 UWP 应用程序通信,因此服务器上的内容没有任何问题。我只是不明白我做错了什么。
    • 啊,我明白了。我需要将 KnownType 属性放在基类上,并将派生自该类的类型作为属性的参数。但问题在于项目的结构使得基类与派生类分开,因此我无法从基类的范围内引用派生类。这种情况如何添加属性?
    猜你喜欢
    • 1970-01-01
    • 2014-09-16
    • 2013-05-10
    • 2019-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多