# Tuesday, December 16, 2008

This took me quite a while to figure out, so I thought I’d post it. :) 

I’ve got a Silverlight application that calls a web service, that gets some data from SQL Server via LINQ.  The LINQ statement returns an IEnumerable<QuestionCategory>, and each QuestionCategory has a property which is IEnumerable<Question>:

 

    public class QuestionCategory

    {

        public string CategoryName { get; set; }

        public int CategoryId { get; set; }

        public int Order { get; set; }

        public IEnumerable<Question> Questions { get; set; }

    }

 

    public class Question

    {

        public string Text { get; set; }

        public ScaledAnswer? Answer { get; set; }

    }

            using (EvalDataContext context = new EvalDataContext())

            {

                var x = from category in context.EvalQuestionCategories

                        select new QuestionCategory()

                        {

                            CategoryId = category.CategoryID,

                            CategoryName = category.CategoryText,

                            Order = (int)category.CategoryOrder,

                            Questions = (from q in category.EvalQuestions select new Question() { Text = q.QuestionText }).ToList()

                        };

                return x.ToList();

            }

This all worked just fine until it got across the wire to the Silverlight client, where I was consistently getting “The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.”  Helpful?  Sort of.  The first step was to track down what was actually getting serialized on the server side, and why that should be a problem.  Several debugger sessions later, turns out the “Questions” property of the QuestionCategory was really an ObjectMaterializer (an internal LINQ class) and not really a collection of Question objects, despite (and this is the part that really got me) the fact that I was explicitly calling .ToList() on the LINQ expression.  (FYI: .ToArray() produced the same results)

Given the above, it makes sense that this counts as “not a meaningful reply”, but what’s the solution?  ToList or ToArray should have caused the LINQ statement to be realized, I would think, but no.  In the end, it was pretty straightforward, although I’m not sure I agree that it should be necessary. 

    public class QuestionCategory

    {

        public string CategoryName { get; set; }

        public int CategoryId { get; set; }

        public int Order { get; set; }

        public List<Question> Questions { get; set; }

    }

By changing the Questions property from IEnumerable<Question> to List<Question> it was realized in time, and everything was serialized/deserialized properly. 

It took an embarrassingly long time to figure this out, so hopefully this will be googled by some other poor soul facing the same problem. :-)

Tuesday, December 16, 2008 11:19:03 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [3]  | 
Tuesday, December 16, 2008 2:32:41 PM (Pacific Standard Time, UTC-08:00)
At first I thought this was going to be the covariance/contravariance problem, but this is good too.

I probably wouldn't have thought to have IEnumerable<T> in a DataContract anyhow - it sort of baffles me that the serializer can cope.
Jeff Paulsen
Tuesday, December 16, 2008 2:59:32 PM (Pacific Standard Time, UTC-08:00)
I just figured IEnumerable meant "a collection of somethings", but didn't realize that it had implications for realization.
Tuesday, December 16, 2008 8:31:41 PM (Pacific Standard Time, UTC-08:00)
Sorry for being rude, but, why would you put ANY interface on a data contract? How am I supposed to deserialize something when I don't know what it actually is? Think about it. MS made a mistake when they hard coded special handling of IEnumerable on data contracts. This may have nothing at all to do with your actual problem, but still.
El Guapo
Comments are closed.