c# - 返回 Azure TableEntity 对象列表时出现 SerializationException

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

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

这是我在 Controller 中的代码

 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; }

}

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

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;
    }

有什么想法吗?

以下是输出窗口中列出的异常(exception)情况。

抛出异常: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”

最佳答案

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

TableEntity serialization

您有几个选择:

  1. 继承自 ITableEntity 接口(interface)而不是 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;
}

在你的 Controller 中:

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。

希望有所帮助...祝你好运!

关于c# - 返回 Azure TableEntity 对象列表时出现 SerializationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36594742/

相关文章:

c# - 如何使用 Linq 在 C# 中创建 if else 语句

c# - 在 Silverlight 中向 Intellisense 公开属性

Azure 表查询

c# - 自创建数据库以来,支持 '--Context' 上下文的模型已更改 - 但 db 是新的生产数据库

javascript - 我如何通过javascript设置microsoft情感api的url

c# - WebAPI 接受不同的整数值

c# - 自动映射器。如果源成员为空则映射

c# - Windows Phone 8 文本选择选项

c# - 如何降低GetHashCode的复杂度

c# - 是否可以使用 System.Net.Http.HttpClient 的持久连接?