Reputation: 2346
i have an MVC application and i execute a query to get a table content. But when i try to return the result back to the client i get an ExceptionMessage: "Cannot return Binary type for a String typed property."
Controller code:
public IEnumerable<DynamicTableEntity> Get(string table)
{
var storageAccount = CloudStorageAccount.Parse(<StorageConnectionString>);
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
CloudTable table = tableClient.GetTableReference(table);
TableQuery<DynamicTableEntity> query = new TableQuery<DynamicTableEntity>()
.Where("")
.Take(50);
return table.ExecuteQuery(query);
}
When i execute Get table i get 500 Internal Server Error
ExceptionMessage: "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'."
InnerException:
ExceptionMessage: "Cannot return Binary type for a String typed property."
But when i debug the "Get" function i see that all data received as expected and this is a Json
serialization issue. I tried to use CloudTableClient PayloadFormat
and DefaultRequestOptions
with no success.
Any suggestions?
Stack Trace:
{
Message: "An error has occurred."
ExceptionMessage: "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'."
ExceptionType: "System.InvalidOperationException"
StackTrace: null
InnerException: {
Message: "An error has occurred."
ExceptionMessage: "Error getting value from 'BinaryValue' on 'Microsoft.WindowsAzure.Storage.Table.EntityProperty'."
ExceptionType: "Newtonsoft.Json.JsonSerializationException"
StackTrace: " at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType) at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType) at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value) at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding) at System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding) at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content) at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__1b.MoveNext()"
InnerException: {
Message: "An error has occurred."
ExceptionMessage: "Cannot return Binary type for a Boolean typed property."
ExceptionType: "System.InvalidOperationException"
StackTrace: " at Microsoft.WindowsAzure.Storage.Table.EntityProperty.EnforceType(EdmType requestedType) at Microsoft.WindowsAzure.Storage.Table.EntityProperty.get_BinaryValue() at GetBinaryValue(Object ) at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)"
}-
}-
}
Upvotes: 3
Views: 5698
Reputation: 1
assuming all values are String values, this line is enough
var tables = Record.Properties.Select(x => x.Value.StringValue).ToList();
if you have more types you can create a switch function to get the value of each type.
Upvotes: 0
Reputation: 3384
I have implemented an API that serializes DynamicTableEntity objects into Json strings and deserializes Json strings back to DynamicTableEntity objects.
Please have a look at: https://www.nuget.org/packages/DynamicTableEntityJsonSerializer/
Usage
//Instantiate serializer
DynamicTableEntityJsonSerializer serializer = new DynamicTableEntityJsonSerializer();
//Serialize DynamicTableEntity into Json string
string serializedEntity = serializer.Serialize(dynamicTableEntity);
//Deserialize DynamicTableEntity from Json string
DynamicTableEntity dynamicTableEntity = serializer.Deserialize(serializedEntity);
Any comments welcome:)
Upvotes: 1
Reputation: 7465
I know it does not respond exactly to your question, but I managed to serialize in xml, you may try to tweak that to make it work in json.
public static byte[] Serialize(this ITableEntity entity)
{
MemoryStream ms = new MemoryStream();
using(var messageWriter = new ODataMessageWriter(new Message(ms), new ODataMessageWriterSettings()))
{
// Create an entry writer to write a top-level entry to the message.
ODataWriter entryWriter = messageWriter.CreateODataEntryWriter();
var writeODataEntity =typeof(TableConstants).Assembly.GetType("Microsoft.WindowsAzure.Storage.Table.Protocol.TableOperationHttpWebRequestFactory")
.GetMethod("WriteOdataEntity", BindingFlags.NonPublic | BindingFlags.Static);
writeODataEntity.Invoke(null, new object[] { entity, TableOperationType.Insert, null, entryWriter });
return ms.ToArray();
}
}
public static void Deserialize(this ITableEntity entity, byte[] value)
{
MemoryStream ms = new MemoryStream(value);
using(ODataMessageReader messageReader = new ODataMessageReader(new Message(ms), new ODataMessageReaderSettings()))
{
ODataReader reader = messageReader.CreateODataEntryReader();
var readAndUpdateTableEntity = typeof(TableConstants).Assembly.GetType("Microsoft.WindowsAzure.Storage.Table.Protocol.TableOperationHttpResponseParsers")
.GetMethod("ReadAndUpdateTableEntity", BindingFlags.NonPublic | BindingFlags.Static);
reader.Read();
readAndUpdateTableEntity.Invoke(null, new object[] { entity, reader.Item, 31, null });
}
}
internal class Message : IODataResponseMessage
{
private readonly Stream stream;
private readonly Dictionary<string, string> headers = new Dictionary<string, string>();
public Message(Stream stream)
{
this.stream = stream;
SetHeader("Content-Type", "application/atom+xml");
}
public string GetHeader(string headerName)
{
string value;
headers.TryGetValue(headerName, out value);
return value;
}
public void SetHeader(string headerName, string headerValue)
{
this.headers.Add(headerName, headerValue);
}
public Stream GetStream()
{
return this.stream;
}
public IEnumerable<KeyValuePair<string, string>> Headers
{
get
{
return this.headers;
}
}
public int StatusCode
{
get;
set;
}
}
Upvotes: 0
Reputation: 1269
Unfortunately, DynamicTableEntity and EntityProperty are not serializable currently. POCO entities on the other hand are serializable. If you deserialize into an object that derives from TableEntity then this should be serializable out of the box. If you want to do a truly heterogeneous query where you have to deal with different types being stored in a single table and returned as the query result, you can use the EntityResolver to resolve to the appropriate type.
Upvotes: 1