نحوه رفع مشکل Optionsetها

یکی از امکانات بسیار خوب Microsoft CRM مربوط به وب‌سرویس‌های متنوع آن است. انواع سرویس‌ها با قابلیت استفاده سمت Client و سمت Server، امکان سفارشی‌سازی‌های بی‌نظیری را فراهم می‌نمایند. اخیراً یکی از مشتریان برای استفاده از داده‌های داخل CRM در سیستم فروشندگانش، نیاز به استفاده از سرویس‌های CRM داشت. از طرفی به دلیل پویایی محیط فروشندگان، امکان استفاده از dllها فراهم نبود. بنابراین تصمیم گرفته شد که از وب سرویس استفاده شود. با وجود این‌که بسیاری از سرویس‌های Dynamics CRM به شکل آماده قابل استفاده هستند، تنظیمات مربوط به آن، خطایابی و نحوه استفاده از آن بسیار حائز اهمیت است. در ادامه به خطایی رایج در وب سرویس نسخه 2011 اشاره خواهیم کرد، که به شکلی مشابه در نسخه 2013 نیز تکرار شده است.

مشکلی که معمولاً رخ می‌دهد در هنگام Query گرفتن از فیلدهای از نوع Optionset و EntityReference است. برای مثال فرض کنید که از کد زیر برای دریافت اطلاعات اشخاص استفاده می‌شود:

 

OrganizationServiceClient orgClient = new OrganizationServiceClient();
orgClient.ClientCredentials.Windows.ClientCredential =

new System.Net.NetworkCredential("username@contoso.com", "Password");
QueryExpression qe = new QueryExpression() { EntityName = "contact" };
qe.Criteria = new FilterExpression();
qe.Criteria.Conditions = new ConditionExpression[] { new ConditionExpression()

{ AttributeName = "statuscode", Operator = ConditionOperator.Equal, Values = new string[] { 1 } } };
qe.ColumnSet = new ColumnSet() { Columns = new string [] { "statuscode", "ownerid" }};
EntityCollection entities = orgClient.RetrieveMultiple(qe);

 

درصورت استفاده از کد بالا با خطای زیر مواجه خواهیم شد:

 

The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://schemas.microsoft.com/xrm/2011/Contracts/Services:RetrieveMultipleResult. The InnerException message was 'Error in line 1 position 838. 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:EntityReference'. The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver or add the type corresponding to 'EntityReference' 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.

 

درصورت بروز این مشکل مراحل زیر را طی نمایید:

1- یک class با نام دلخواه در همان پروژه ایجاد نمایید.

2- namespace داخل کلاس را دقیقاً مشابه همان namespace مربوط به service reference قرار دهید.

3- داخل namespace محتوای زیر را وارد نمایید:

 

[System.Runtime.Serialization.KnownTypeAttribute(typeof(OptionSetValue))]

[System.Runtime.Serialization.KnownTypeAttribute(typeof(EntityReference))]
public partial class Entity { }
 
[System.Runtime.Serialization.KnownTypeAttribute(typeof(OptionSetValue))]
[System.Runtime.Serialization.KnownTypeAttribute(typeof(EntityReference))]
public partial class EntityCollection { }
 
[System.Runtime.Serialization.KnownTypeAttribute(typeof(EntityReference))]
[System.Runtime.Serialization.KnownTypeAttribute(typeof(PrincipalAccess))]
[System.Runtime.Serialization.KnownTypeAttribute(typeof(OptionSetValue))]
public partial class OrganizationRequest { }
 
از پروژه Build گرفته و فیلدهای Optionset و Entity Refrence را Query نمایید.