【问题标题】:SerializationException when returning List of Azure TableEntity objects返回 Azure TableEntity 对象列表时出现 SerializationException
【发布时间】:2016-04-13 09:52:36
【问题描述】:

使用 WebAPI 返回 TableEntities 列表时,我收到 500 内部服务器错误。当我查看 Visual Studio 中的输出时,我发现我收到了这些“System.Runtime.Serialization.SerializationException”。

这是我在控制器中的代码

 public IEnumerable<ContactEntity> Get()
    {
        var creds = new StorageCredentials("MyAccountName", "MyKey");
        var storageAccount = new CloudStorageAccount(creds, false);

        // Create the table client.
        var tableClient = storageAccount.CreateCloudTableClient();

        // Retrieve a reference to the table.
        var contactsTable = tableClient.GetTableReference("contacts");

        // Create the table if it doesn't exist.
        contactsTable.CreateIfNotExists();

        // Construct the query operation for all contact entities
        var query = new TableQuery<ContactEntity>();

        var items = contactsTable.ExecuteQuery<ContactEntity>(query).ToList();

        return items;
    }

这是我的自定义 TableEntity 代码

    [Serializable]
public class ContactEntity: TableEntity
{

    public ContactEntity(string firstName, string lastName)
    {
        this.PartitionKey = lastName;
        this.RowKey = firstName;
    }

    public ContactEntity() { }

    public string Email { get; set; }

}

在控制器中,如果我手动创建实体列表,则不会出现序列化问题。

public IEnumerable<ContactEntity> Get()
    {
        var creds = new StorageCredentials("MyAccountName", "MyKey");
        var storageAccount = new CloudStorageAccount(creds, false);

        // Create the table client.
        var tableClient = storageAccount.CreateCloudTableClient();

        // Retrieve a reference to the table.
        var contactsTable = tableClient.GetTableReference("contacts");

        // Create the table if it doesn't exist.
        contactsTable.CreateIfNotExists();

        // Construct the query operation for all contact entities
        var query = new TableQuery<ContactEntity>();

        var items = contactsTable.ExecuteQuery<ContactEntity>(query).ToList();

        var manualList = new List<ContactEntity>() { };

        manualList.Add(new ContactEntity { PartitionKey = items[0].PartitionKey, RowKey = items[0].RowKey, ETag = items[0].ETag, Timestamp = items[0].Timestamp });
        manualList.Add(new ContactEntity { PartitionKey = items[1].PartitionKey, RowKey = items[1].RowKey, ETag = items[1].ETag, Timestamp = items[1].Timestamp });


        return manualList;
    }

有什么想法吗?

以下是输出窗口中列出的例外情况。

抛出异常:mscorlib.dll 中的“System.Runtime.Serialization.SerializationException” 抛出异常:mscorlib.dll 中的“System.Runtime.Serialization.SerializationException” 抛出异常:Newtonsoft.Json.dll 中的“System.Runtime.Serialization.SerializationException” 抛出异常:Newtonsoft.Json.dll 中的“System.Runtime.Serialization.SerializationException” 抛出异常:Newtonsoft.Json.dll 中的“System.Runtime.Serialization.SerializationException” 抛出异常:Newtonsoft.Json.dll 中的“System.Runtime.Serialization.SerializationException” 抛出异常:Newtonsoft.Json.dll 中的“System.Runtime.Serialization.SerializationException” 抛出异常:Newtonsoft.Json.dll 中的“System.Runtime.Serialization.SerializationException” 抛出异常:mscorlib.dll 中的“System.Runtime.Serialization.SerializationException” 抛出异常:mscorlib.dll 中的“System.Runtime.Serialization.SerializationException”

【问题讨论】:

  • 您可以发布异常的详细信息吗?我认为这是因为实体附加到云表...
  • 添加了输出窗口中列出的异常

标签: c# azure asp.net-web-api azure-table-storage


【解决方案1】:

由于内部委托成员等原因,从 TableEntity 继承的类型无法序列化。见下文:

TableEntity serialization

你有几个选择:

  1. 从 ITableEntity 接口而不是 TableEntity 继承...您必须自己实现核心 TableEntity 行为(一般来说还不错),如果您愿意,这也为您提供了实现序列化的机会

  2. 更改您的 Web API 以输出仅包含您要返回的实体属性的单独类型,并为您的实体类型实现转换函数,如下所示:

在 ContactEntity 类中:

public JObject ToJson()
{
    var jo = new JObject();

    jo["PartitionKey"] = PartitionKey;
    jo["RowKey"] = RowKey;
    jo["Email"] = Email;

    // etc

    return jo;
}

在您的控制器中:

public IEnumerable<JObject> Get()
{
    // Create the table client.
    var tableClient = _account.CreateCloudTableClient();

    // Retrieve a reference to the table.
    var contactsTable = tableClient.GetTableReference("contacts");

    // Create the table if it doesn't exist.
    contactsTable.CreateIfNotExists();

    // Construct the query operation for all contact entities
    var query = new TableQuery<ContactEntity>();

    var items = contactsTable.ExecuteQuery<ContactEntity>(query).ToList();

    return items.Select(i => i.ToJson());
}

注意从返回 ContactEntity 的 IEnumerable 到 JObject 的 IEnumerable 的切换。如果您愿意,也可以定义一个单独的类并使用它来代替 JObject。

希望对您有所帮助...祝您好运!

【讨论】:

    【解决方案2】:

    JshL 建议的另一个替代方法是,您可以更改您的 web api 以返回 json 序列化 DynamicTableEntities 的 IEnumerable。在客户端将 json 反序列化回 DynamicTableEntity 并处理将其转换为您的具体类,如果您想要或只是将其作为 DynamicTableEntity 使用。

    你可以看看我在这里实现的 DynamicTableEntity json 序列化器: https://www.nuget.org/packages/DynamicTableEntityJsonSerializer/

    【讨论】:

    • DynamicTableEntityJsonSerializer is a namespace but is used like a type 当我们尝试演示时。
    • 命名空间和类型都具有相同的名称 DynamicTableEntityJsonSerializer 要么将具有完整路径的类称为 DynamicTableEntityJsonSerializer.DynamicTableEntityJsonSerializer ,要么仅使用该类的别名。如果它可以帮助您解决问题,请不要羞于投票:)
    猜你喜欢
    • 1970-01-01
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    • 2012-07-21
    • 1970-01-01
    • 1970-01-01
    • 2013-01-17
    • 1970-01-01
    相关资源
    最近更新 更多