WCF 反序列化 - 反序列化器不知道映射到此名称的任何类型

发布于 2024-11-09 02:03:23 字数 3233 浏览 5 评论 0原文

我有一个与云中的 CRM 2011 通信的 WCF 服务。我使用提供的 crmsvcutil.exe 为 CRM 中的所有对象生成实体。我有一个接口 IProduct ,它指向 GetAllProducts() ,需要返回所有产品的列表。如果我在客户端(C# 控制台应用程序)时单步执行我的服务,Linq 查询将具有预期的产品列表。但是当它尝试将其返回到调用应用程序时,我收到一个错误:

The InnerException 消息是“第 1 行位置 688 中的错误。元素”http://schemas.datacontract.org/2004/07/System。 Collections.Generic:value' 包含映射到名称“http://schemas.microsoft.com/xrm/2011/Contracts:OptionSetValue”的类型的数据。解串器不知道映射到该名称的任何类型。考虑使用 DataContractResolver 或将与“OptionSetValue”对应的类型添加到已知类型列表 - 例如,通过使用 KnownTypeAttribute 属性或将其添加到传递给 DataContractSerializer 的已知类型列表。请参阅 InnerException 了解更多详细信息。"}

这只发生在复杂数据类型中。如果我返回一个简单的字符串或 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()
            {

            }
        }
    }

I have a WCF service that communicates with CRM 2011 in the Cloud. I used the provided crmsvcutil.exe to generate entities for all objects in CRM. I have an interface IProduct that points to GetAllProducts() that needs to return a list of all Products. If I step thru my service when the client (C# console application), the Linq query has the list of products as expected. But when it tries to return it to the calling application, I get an error:

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."}.

This only occurs with complex data types. If I return a simple string or int, no problems there. As a POC that I can return complex types, I created a class called ComplexPerson, and a method called GetPerson(int Id) to return a simple object. This worked fine (as I had to decorate the class myself).

    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()
            {

            }
        }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

习ぎ惯性依靠 2024-11-16 02:03:23

这就是我让它发挥作用的方式。就我而言,我有三个项目:-

  • 一个“服务契约”类库项目,其中包含由 CrmSvcUtil 生成的 cs 文件和我的 WCF 接口(IMyService 或其他)。该项目引用了常用的 CRM DLL(Microsoft.Xrm.Sdk、MicrosoftXrm.Client、Microsoft.Crm.Sdk.Proxy)以及这些依赖的其他DLL(例如 System.Data.Services.dll 等)。

  • WCF 服务项目(引用上述项目)。这里是实现上述项目中的接口的.svc。该项目还引用与上述相同的 CRM DLL。

  • 我的客户项目。这参考了上述服务合同项目。它还引用两个 CRM DLL(Microsoft.Xrm.Sdk 和 Microsoft.Xrm.Client)。您可能还需要添加一些依赖项(例如 System.Runtime.Serialization)。

现在以通常的方式添加服务引用。现在,编写代码来实例化并调用服务代理上的操作。假设你需要引用CRM实体类,那么你只需要添加一个“using xxx;” (其中 xxx 是您在 CrmSvcUtil.exe 命令行中使用的命名空间)。

希望这有帮助
安迪

This is how I got it to work. In my case I have three projects:-

  • A "service contract" class library project containing the cs file generated by CrmSvcUtil, and my WCF interface (IMyService or whatever). This project references the usual CRM DLLs (Microsoft.Xrm.Sdk, MicrosoftXrm.Client, Microsoft.Crm.Sdk.Proxy), plus others that these depend on (e.g. System.Data.Services.dll, etc).

  • The WCF service project (which references the above project). In here is the .svc that implements the interface in the above project. The project also references the same CRM DLLs as above.

  • My client project. This references the above service contract project. It also references two of the CRM DLLs (Microsoft.Xrm.Sdk & Microsoft.Xrm.Client). You might also need to add a couple of dependencies (e.g. System.Runtime.Serialization).

Now add a service reference in the usual way. Now, write your code to instantiate and call an operation on the service proxy. Assuming you need to reference the CRM entity classes, you just need to add a "using xxx;" (where xxx is the namespace you used in the command line of CrmSvcUtil.exe).

Hope this helps
Andy

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文