2016-04-13 2 views
0

При возврате списка таблиц с использованием WebAPI я получаю 500 Internal Server Error. Когда я смотрю вывод в Visual Studio, я вижу, что получаю это «System.Runtime.Serialization.SerializationException».SerializationException при возврате списка объектов Azure TableEntity

Вот мой код в контроллере

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

Любые идеи, почему?

Вот исключения, перечисленные в окне вывода.

Исключение брошено: 'System.Runtime.Serialization.SerializationException' в 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 Исключение брошено: 'Система .Runtime.Serialization.SerializationException 'в Newtonsoft.Json.dll Исключение брошено:' System.Runtime.Serialization.SerializationException 'в Newtonsoft.Json.dll Exc eption thrown: 'System.Runtime.Serialization.SerializationException' в Newtonsoft.Json.dll Исключение брошено: 'System.Runtime.Serialization.SerializationException' в mscorlib.dll Исключение брошено: 'System.Runtime.Serialization.SerializationException' в mscorlib .dll

+0

Вы можете разместить информацию о исключении? Я думаю, что это связано с тем, что сущности привязаны к облачному ... – Thomas

+0

добавлены исключения, перечисленные в окне вывода –

ответ

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

Обратите внимание на переход от возвращения IEnumerable из ContactEntity в IEnumerable из JObject. Вы также можете определить отдельный класс и использовать это вместо JObject, если хотите.

Надеюсь, что это поможет ... удачи!

1

Дополнительная альтернатива предложениям JshL, вы можете изменить свой веб-api, чтобы вернуть IEnumerable из json serialized DynamicTableEntities. И на стороне клиента десериализуйте json обратно в DynamicTableEntity и обработайте это преобразование в свой конкретный класс, если хотите или просто используйте его как DynamicTableEntity.

Вы можете посмотреть на DynamicTableEntity JSon сериализаторе Я реализовал здесь: https://www.nuget.org/packages/DynamicTableEntityJsonSerializer/

+0

'DynamicTableEntityJsonSerializer - это пространство имен, но используется как тип, когда мы пробуем демонстрацию. –

+1

Оба пространства имен и тип типа имеют одно и то же имя DynamicTableEntityJsonSerializer либо относятся к классу с полным путем как DynamicTableEntityJsonSerializer.DynamicTableEntityJsonSerializer, либо просто используют псевдоним для класса. И если это поможет вам решить вашу проблему, не стесняйтесь повышать :) –