locked
Did the DataContractSerializer change in RTM? RRS feed

  • Question

  • After installing the Win8 and VS2012 RTM bits my Serialize method throws an exception.  It complains of needing a list of knowntypes.  Before RTM, I could easily pass in the type I was expecting to serialize. 

    Here is the code that used to work:

    public async Task SerializeDataSetAsync()
    {
    	StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
    	StorageFile sfCats = await storageFolder.CreateFileAsync(this.InvFileName, CreationCollisionOption.ReplaceExisting);
    	var dcs = new DataContractSerializer(typeof(ObservableCollection<Category>));
    
    	using (IRandomAccessStream raStream1 = await sfCats.OpenAsync(FileAccessMode.ReadWrite))
    	{
    		dcs.WriteObject(raStream1.AsStream(), this);
    	}
    }
    

    When I add a list of knowntypes, it still blows.

    public async Task SerializeDataSetAsync()
    {
    	StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
    	StorageFile sfCats = await storageFolder.CreateFileAsync(this.InvFileName, CreationCollisionOption.ReplaceExisting);
    
    	List<Type> knownTypes = new List<Type>();
    	knownTypes.Add(typeof(Category));
    	knownTypes.Add(typeof(Item));
    	var dcs = new DataContractSerializer(typeof(ObservableCollection<Category>), knownTypes);
    
    	using (IRandomAccessStream raStream1 = await sfCats.OpenAsync(FileAccessMode.ReadWrite))
    	{
    		dcs.WriteObject(raStream1.AsStream(), this);
    	}
    }
    


    Thanks, Terrence

    Saturday, August 18, 2012 1:57 PM

Answers

  • the method you showed is in your viewmodel?

    you have this:

    dcs.WriteObject(raStream1.AsStream(), this);
    

    so you are serializing the viewmodel then (this == the viewmodel)
    • Marked as answer by Terrence_ Saturday, August 18, 2012 7:32 PM
    Saturday, August 18, 2012 6:53 PM

All replies

  • this worked fine for me in RTM

    var file = await ApplicationData.Current.LocalFolder.CreateFileAsync("ewwe", CreationCollisionOption.ReplaceExisting); using (var stream = await file.OpenStreamForWriteAsync()) { Dictionary<string, object> dictonary = new Dictionary<string, object>(); dictonary.Add("hello", "hello"); var knownTypes = dictonary.Values.Select(x => x.GetType()).Distinct().ToArray(); DataContractSerializer serializer = new DataContractSerializer(typeof(Dictionary<string, object>), knownTypes); serializer.WriteObject(stream, dictonary); await stream.FlushAsync(); } But all objects

    So maybe dont use AsStream

    Saturday, August 18, 2012 3:16 PM
  • The following is a RTM solution that does not require 'knownTypes':

    <Page
        x:Class="ForInfo2.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:ForInfo2"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <StackPanel>
                <Button Content="Serialize" Click="Button_Click_1"/>
                <Button Content="Deserialize" Click="Button_Click_2"/>
                <TextBox Text="{Binding Date}" Width="300" IsReadOnly="True" HorizontalAlignment="Left" /> 
                <ListView x:Name="lv" Width="300" Height="600" HorizontalAlignment="Left" Background="LightBlue" ItemsSource="{Binding ItemsSource}">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <TextBlock Text="*** Category ***"/>
                                <TextBlock Text="{Binding Path=Id}"/>
                                <TextBlock Text="{Binding Path=Name}"/>
                                <TextBlock Text="{Binding Path=ItemList[0].Id}"/>
                                <TextBlock Text="--- Item ---"/>
                                <TextBlock Text="{Binding Path=Item.Id}"/>
                                <TextBlock Text="{Binding Path=Item.Name}"/>
                            </StackPanel>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </StackPanel>
        </Grid>
    </Page>

    ---

    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Navigation;
    
    namespace ForInfo2
    {
        /// <summary>
        ///
        /// </summary>
        public sealed partial class MainPage : Page, INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            private void OnPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
            private readonly ObservableCollection<Category> itemsSource = new ObservableCollection<Category>();
            public ObservableCollection<Category> ItemsSource
            {
                get { return itemsSource; }
            }
            string date;
            public string Date
            {
                get { return date; }
                set { date = value; OnPropertyChanged("Date"); }
            }
            public MainPage()
            {
                this.DataContext = this;
                this.InitializeComponent();
            }
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
            static int offset = 1;
            private async void Button_Click_1(object sender, RoutedEventArgs e)
            {
                Item item;
                Category category;
    
                // Exec
                this.Date = DateTime.Now.ToString("hh.mm.ss");
                for (int i = 1; i < 5; i++)
                {
                    category = new Category() { Id = offset, Name = String.Format("CatgName:{0}", offset++) };
                    item = new Item() { Id = offset, Name = String.Format("ItemName:{0} {1}", offset++, this.Date) };
                    category.Item = item;
                    category.ItemList.Add(item);
                    category.ItemList.Add(item);
                    SerialData.List.Add(category);
                }
                // ...
                await SerialExec.Save();
            }
    
            private async void Button_Click_2(object sender, RoutedEventArgs e)
            {
                // Exec
                await SerialExec.Restore();
                // ...
                foreach (Category item in SerialData.List)
                {
                    itemsSource.Add(item);
                    lv.ScrollIntoView(item);
                }
            }
        }
    }

    ---

    using System.Collections.ObjectModel;
    
    namespace ForInfo2
    {
        public class SerialData
        {
            private static ObservableCollection<Category> list = new ObservableCollection<Category>();
            public static ObservableCollection<Category> List
            {
                get { return list; }
                set { list = value; }
            }
        }
    }
    using System;
    using System.Collections.ObjectModel;
    using System.IO;
    using System.Runtime.Serialization;
    using System.Threading.Tasks;
    using Windows.Storage;
    using Windows.Storage.Streams;
    
    namespace ForInfo2
    {
        public class SerialExec
        {
            private static StorageFolder folder = ApplicationData.Current.LocalFolder;
            private const string fileName = "Category.xml";
            /// <summary>
            /// 
            /// </summary>
            static async public Task Save()
            {
                StorageFile sessionFile = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
                DataContractSerializer sessionSerializer = new DataContractSerializer(typeof(ObservableCollection<Category>));
                // ...
                using (IRandomAccessStream sessionRandomAccess = await sessionFile.OpenAsync(FileAccessMode.ReadWrite))
                {
                    sessionSerializer.WriteObject(sessionRandomAccess.AsStream(), SerialData.List);
                }
            }
            /// <summary>
            /// 
            /// </summary>
            static async public Task Restore()
            {
                StorageFile sessionFile = await folder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists);
                if (sessionFile == null)
                    return;
                // ...
                IInputStream sessionInputStream = await sessionFile.OpenReadAsync();
                DataContractSerializer sessionSerializer = new DataContractSerializer(typeof(ObservableCollection<Category>));
                SerialData.List = (ObservableCollection<Category>)sessionSerializer.ReadObject(sessionInputStream.AsStreamForRead());
            }
        }
    }

    ---

    using System;
    using System.Collections.Generic;
    using System.Runtime.Serialization;
    
    namespace ForInfo2
    {
        [KnownType(typeof(Category))]
        [DataContract(Name = "Category", Namespace = "http://www.mySelf.com")]
        public class Category
        {
            [DataMember()]
            public int Id { get; set; }
            
            [DataMember()]
            public String Name { get; set; }
    
            [DataMember()]
            public Item Item { get; set; }
     
            [DataMember()]
            public IList<Item> ItemList { get; set; }
    
            public Category()
            {
                this.ItemList = new List<Item>();
            }
        }
    }

    ---

    using System;
    using System.Runtime.Serialization;
    
    namespace ForInfo2
    {
        [KnownType(typeof(Item))]
        [DataContract(Name = "Item", Namespace = "http://www.mySelf.com")]
        public class Item
        {
            [DataMember()]
            public int Id { get; set; }
            
            [DataMember()]
            public String Name { get; set; }
        }
    }


    • Edited by ForInfo Saturday, August 18, 2012 5:01 PM
    Saturday, August 18, 2012 4:59 PM
  • i agree knownTypes shouldnt be nessary.. in webradio not using it neither
    Saturday, August 18, 2012 5:07 PM
  • So here is the message.

      Message=Type 'NVIN.DataModel.ViewModel' with data contract name

      'ViewModel:http://schemas.datacontract.org/2004/07/NVIN.DataModel' is not expected.

    I am not serializing the ViewModel.  My serialzier code is in my ViewModel class and the I an serializing a collection on the ViewModel.


    Thanks, Terrence

    Saturday, August 18, 2012 6:49 PM
  • the method you showed is in your viewmodel?

    you have this:

    dcs.WriteObject(raStream1.AsStream(), this);
    

    so you are serializing the viewmodel then (this == the viewmodel)
    • Marked as answer by Terrence_ Saturday, August 18, 2012 7:32 PM
    Saturday, August 18, 2012 6:53 PM
  • Dave thanks so much for inspecting my code so closely.  I was going to serialize the whole ViewModel, but changed back to serializing just the collection and I forgot to change that from this to this.Categories.

    I wish I could buy you a beer.

    And thank you for the pdf of the document.


    Thanks, Terrence

    Saturday, August 18, 2012 7:32 PM
  • Thank you for your great post of code, it helped me a bunch.

    Thanks, Terrence

    Saturday, August 18, 2012 7:32 PM