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

时间:2016-04-13 09:52:36

标签: 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;
    }

任何想法为什么?

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

抛出异常:&#39; System.Runtime.Serialization.SerializationException&#39;在mscorlib.dll中 抛出异常:&#39; System.Runtime.Serialization.SerializationException&#39;在mscorlib.dll中 抛出异常:&#39; System.Runtime.Serialization.SerializationException&#39;在Newtonsoft.Json.dll中 抛出异常:&#39; System.Runtime.Serialization.SerializationException&#39;在Newtonsoft.Json.dll中 抛出异常:&#39; System.Runtime.Serialization.SerializationException&#39;在Newtonsoft.Json.dll中 抛出异常:&#39; System.Runtime.Serialization.SerializationException&#39;在Newtonsoft.Json.dll中 抛出异常:&#39; System.Runtime.Serialization.SerializationException&#39;在Newtonsoft.Json.dll中 抛出异常:&#39; System.Runtime.Serialization.SerializationException&#39;在Newtonsoft.Json.dll中 抛出异常:&#39; System.Runtime.Serialization.SerializationException&#39;在mscorlib.dll中 抛出异常:&#39; System.Runtime.Serialization.SerializationException&#39;在mscorlib.dll中

2 个答案:

答案 0 :(得分:1)

由于内部委托成员等原因,无法序列化继承自TableEntity的类型。请参阅以下内容:

TableEntity serialization

您有几个选择:

  1. 从ITableEntity接口而不是TableEntity继承...你必须自己实现核心TableEntity行为(通常也不是太糟糕),如果你愿意,这也让你有机会实现序列化

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

  3. 在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。

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

答案 1 :(得分:1)

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

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