Десериализация WCF - десериализатор не знает ни одного типа, который сопоставляется с этим именем - PullRequest
2 голосов
/ 23 мая 2011

У меня есть служба WCF, которая взаимодействует с CRM 2011 в облаке.Я использовал предоставленный crmsvcutil.exe для генерации сущностей для всех объектов в CRM.У меня есть интерфейс IProduct, который указывает на GetAllProducts(), который должен вернуть список всех продуктов.Если я зайду через свой сервис, когда клиент (консольное приложение C #), запрос Linq будет содержать список продуктов, как и ожидалось.Но когда он пытается вернуть его вызывающему приложению, я получаю сообщение об ошибке:

The InnerException message was 'Error in line 1 position 688. Element 'http://schemas.datacontract.org/2004/07/System.Collections.Generic:value' contains data from a type that maps to the name 'http://schemas.microsoft.com/xrm/2011/Contracts:OptionSetValue'. The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver or add the type corresponding to 'OptionSetValue' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details."}.

Это происходит только со сложными типами данных.Если я верну простую строку или int, никаких проблем там нет.Как POC, который я могу вернуть сложные типы, я создал класс с именем ComplexPerson и метод с именем GetPerson(int Id) для возврата простого объекта.Это работало хорошо (поскольку я должен был украсить класс самостоятельно).

    namespace Microsoft.ServiceModel.Samples
    {
        [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
        public interface IProduct
        {
            [OperationContract]
            [ServiceKnownType(typeof(Product))]
            List<Product> GetAllProducts();

            [OperationContract]
            ComplexPerson GetPerson(int Id);
        }

        public class ProductService : IProduct
        {
            private List<Product> _products;
            private OrganizationServiceProxy _serviceProxy;
            private IOrganizationService _service;

            public List<Product> GetAllProducts()
            {
                _products = new List<Product>();
                try
                {
                    //connect to crm
                        var query = orgContext.CreateQuery<Product>();

                        foreach (var p in query)
                        {
                            if (p is Product)
                                _products.Add(p as Product);
                        }

                        return _products;
                }

                // Catch any service fault exceptions that Microsoft Dynamics CRM throws.
                catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault> ex)
                {
                    // You can handle an exception here or pass it back to the calling method.
                    return null;
                }
            }

            public ComplexPerson GetPerson(int Id)
            {
                ComplexPerson person = new ComplexPerson();

                switch (Id)
                {
                    case 2:
                        person.FirstName = "Tim";
                        person.LastName = "Gabrhel";
                        person.BirthDate = new DateTime(1987, 02, 13, 0, 0, 0);
                        break;
                    default:
                        break;
                }

                return person;
            }

        }

        [DataContract]
        public class ComplexPerson
        {
            [DataMember]
            public string FirstName;
            [DataMember]
            public string LastName;
            [DataMember]
            public DateTime BirthDate;

            public ComplexPerson()
            {

            }
        }
    }

1 Ответ

1 голос
/ 30 июня 2011

Вот как я заставил это работать. В моем случае у меня есть три проекта: -

  • Проект библиотеки классов "контракт на обслуживание", содержащий файл cs, созданный CrmSvcUtil, и мой интерфейс WCF (IMyService или любой другой). Этот проект ссылается на обычные библиотеки CRM (Microsoft.Xrm.Sdk, MicrosoftXrm.Client, Microsoft.Crm.Sdk.Proxy) и другие, от которых они зависят (например, System.Data.Services.dll и т. Д.).

  • Сервисный проект WCF (который ссылается на вышеуказанный проект). Здесь находится .svc, который реализует интерфейс в вышеуказанном проекте. Проект также ссылается на те же библиотеки CRM, что и выше.

  • Мой клиентский проект. Это относится к вышеуказанному проекту контракта на обслуживание. Он также ссылается на две библиотеки CRM (Microsoft.Xrm.Sdk & Microsoft.Xrm.Client). Вам также может понадобиться добавить пару зависимостей (например, System.Runtime.Serialization).

Теперь добавьте сервисную ссылку обычным способом. Теперь напишите свой код для создания экземпляра и вызовите операцию на прокси службы. Предполагая, что вам нужно сослаться на классы сущностей CRM, вам просто нужно добавить «using xxx;» (где xxx - это пространство имен, которое вы использовали в командной строке CrmSvcUtil.exe).

Надеюсь, это поможет Andy

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...