I'm trying to implement usage of ServiceStack for faster JSON serialization/deserialization in my .NET MVC4 application.
I have following for deserializing AJAX requests:
Global.asax.cs:
// Remove and JsonValueProviderFactory and add JsonServiceStackValueProviderFactory
ValueProviderFactories.Factories.Remove(ValueProviderFactories.Factories.OfType<JsonValueProviderFactory>().FirstOrDefault());
ValueProviderFactories.Factories.Add(new JsonServiceStackValueProviderFactory());
public sealed class JsonServiceStackValueProviderFactory : ValueProviderFactory
{
public override IValueProvider GetValueProvider(ControllerContext controllerContext)
{
if (controllerContext == null)
throw new ArgumentNullException("controllerContext");
if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
return null;
var reader = new StreamReader(controllerContext.HttpContext.Request.InputStream).BaseStream;
return new DictionaryValueProvider<object>(
ServiceStack.Text.JsonSerializer.DeserializeFromStream<Dictionary<string, object>>(reader).AsExpandoObject(),
CultureInfo.CurrentCulture);
}
}
// http://nine69.wordpress.com/2013/02/02/asp-net-mvc-series-high-performance-json-parser-for-asp-net-mvc/
public static class CollectionExtensions
{
public static ExpandoObject AsExpandoObject(this IDictionary<string, object> dictionary)
{
var epo = new ExpandoObject();
var epoDic = epo as IDictionary<string, object>;
foreach (var item in dictionary)
{
bool processed = false;
if (item.Value is IDictionary<string, object>)
{
epoDic.Add(item.Key, AsExpandoObject((IDictionary<string, object>) item.Value));
processed = true;
}
else if (item.Value is ICollection)
{
var itemList = new List<object>();
foreach (object item2 in (ICollection) item.Value)
if (item2 is IDictionary<string, object>)
itemList.Add(AsExpandoObject((IDictionary<string, object>) item2));
else
itemList.Add(AsExpandoObject(new Dictionary<string, object> {{"Unknown", item2}}));
if (itemList.Count > 0)
{
epoDic.Add(item.Key, itemList);
processed = true;
}
}
if (!processed)
epoDic.Add(item);
}
return epo;
}
}
I am trying to deserialize an object which looks like:
[DataContract]
public class PlaylistItemDto
{
[DataMember(Name = "playlistId")]
public Guid PlaylistId { get; set; }
[DataMember(Name = "id")]
public Guid Id { get; set; }
[DataMember(Name = "sequence")]
public int Sequence { get; set; }
// Store Title on PlaylistItem as well as on Video because user might want to rename PlaylistItem.
[DataMember(Name = "title")]
public string Title { get; set; }
[DataMember(Name = "video")]
public VideoDto Video { get; set; }
[DataMember(Name = "cid")]
public string Cid { get; set; }
public PlaylistItemDto()
{
Id = Guid.Empty;
Title = string.Empty;
}
public static PlaylistItemDto Create(PlaylistItem playlistItem)
{
PlaylistItemDto playlistItemDto = Mapper.Map<PlaylistItem, PlaylistItemDto>(playlistItem);
return playlistItemDto;
}
public static List<PlaylistItemDto> Create(IEnumerable<PlaylistItem> playlistItems)
{
List<PlaylistItemDto> playlistItemDtos = Mapper.Map<IEnumerable<PlaylistItem>, List<PlaylistItemDto>>(playlistItems);
return playlistItemDtos;
}
}
[DataContract]
public class VideoDto
{
[DataMember(Name = "id")]
public string Id { get; set; }
[DataMember(Name = "title")]
public string Title { get; set; }
[DataMember(Name = "duration")]
public int Duration { get; set; }
[DataMember(Name = "author")]
public string Author { get; set; }
[DataMember(Name = "highDefinition")]
public bool HighDefinition { get; set; }
public VideoDto()
{
Id = string.Empty;
Title = string.Empty;
Author = string.Empty;
}
/// <summary>
/// Converts a Domain object to a DTO
/// </summary>
public static VideoDto Create(Video video)
{
VideoDto videoDto = Mapper.Map<Video, VideoDto>(video);
return videoDto;
}
public static List<VideoDto> Create(IEnumerable<Video> videos)
{
List<VideoDto> videoDtos = Mapper.Map<IEnumerable<Video>, List<VideoDto>>(videos);
return videoDtos;
}
}
The first level is deserialized correctly, but the Video object is null. I have been scouring the web for additional documentation, but haven't come up with much. I've found these articles which seem to be relevant:
How to get ServiceStack to serialize / deserialize an expando object with correct types Deserializing JSON into Object
But the first doesn't provide an example -- only mentions some changes to the new versions of ServiceStack. The second shows how to deserialize, but doesn't handle a Stream or ExpandoObjects. The first hints that ExpandoObjects might not be fully supported.
I feel like I am trying to deserialize a pretty simple object. Is there any support for nested levels of objects in ServiceStack? Thanks
You can see full source on GitHub if that is helpful: https://github.com/MeoMix/StreamusServer/blob/development/Streamus/Global.asax.cs