Hi all
We recently installed CRM 2011 and I'm doing some proof of concept work with WCF. I've generated the early bound entity classes using CrmSvcUtil.exe and I've created a solution with two very basic projects - a WCF service and a console app acting as the client. The service simply retrieves a Contact entity and sends it back to the client across WCF - this is working fine.
However when I try to return the Contact *plus* related entities (e.g. Appointments), I get this exception logged on the WCF service side:
There was an error while trying to serialize parameter http://tempuri.org/:GetContactResult. The InnerException message was 'Type 'CheshireSS.MicrosoftCrm2011.Services.Appointment' with data contract name 'Appointment:http://schemas.datacontract.org/2004/07/CheshireSS.MicrosoftCrm2011.Services' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'.
(For info, "CheshireSS.MicrosoftCrm2011.Services" is the namespace specified on the CrmSvcUtil command line, used in the generated .cs file containing the entity classes).
This is the code in my WCF service operation:
CrmDataContext dc = new CrmDataContext("Xrm");
Contact contact = (from c in dc.ContactSet .....etc.....
Relationship rel = new Relationship("Contact_Appointments");
dc.LoadProperty(contact, rel);
return contact;
My solution actually has a third "service contract" project which is a class library containing the .cs class generated by CrmSvcUtil and the interface that my WCF service implements, simply:
[ServiceContract]
public interface IService1
{
[OperationContract]
Contact GetContact();
}
*This post is locked for comments
I have the same question (0)Hi Andy,
The crmutil is great but leaves a bit to be desired if you want to create a wcf to act as a proxy for Xrm. .
There are a couple issues:
Collections are returned as IEnumberable<> which won't get serialzed correctly, we need to return List<>
-This is why you are seeing the problem you are.
The entities are decorated with the datacontract attribute, which would be fine if they also marked the public members as accordingly
-This is why your custom entity fields aren't being seen on the client
I have successfully built a wcf that doesn't requiring the client to reference the crm sdk dll's and will bring in related entites just fine. To make it work, I created a console app that kicks off the crmsvcutil to create the proxy class, then the app reads the file and makes some updates to fix the items above.
Here is a code sample from the latter function (I apologize for the poor formatting):
var sb = new StringBuilder();
File.ReadLines(outputFile).ToList().ForEach(line =>
{
if (line.Contains("[System.Runtime.Serialization.DataContractAttribute()]"))
{
// we don't want this attribute so don't append to 'sb'
}
else if (line.Contains("System.Collections.Generic.IEnumerable"))
{
sb.AppendLine(line.Replace("System.Collections.Generic.IEnumerable", "System.Collections.Generic.List"));
}
else if (line.Contains("return System.Linq.Enumerable.Cast"))
{
var type = line.Substring((line.IndexOf('<') + 1), (line.IndexOf('>') - (line.IndexOf('<') + 1)));
sb.AppendLine(string.Format("\t\t\t\t\treturn new System.Collections.Generic.List<{0}>(System.Linq.Enumerable.Cast<{0}>(collection.Entities));", type));
}
else if (line.Contains("return this.GetRelatedEntities"))
{
var type = line.Substring((line.IndexOf('<') + 1), (line.IndexOf('>') - (line.IndexOf('<') + 1)));
sb.AppendLine(string.Format("{0} as System.Collections.Generic.List<{1}>;", line.TrimEnd(new[] { ';' }), type));
}
else
{
sb.AppendLine(line);
}
});
File.WriteAllText(outputFile, sb.ToString());\
Hope this helps!!
Community Member
2
Christoph Pock
1