locked
Reflection and the CRM 2011 accounts object RRS feed

  • Question

  • Hi,

    I created an integration solution to synchronize SAP data with a CRM 3 implementation.  As part of the update process I used reflection to determine the attribute type.  This resulted in a relatively dynamic and efficient update script.  I'm currently trying to update the script to connect and update a CRM 2011 implementation. 

    Due to limited time I'm trying to repeat the current solution as it has worked well over the past 5+ years.  I have most of the functionality working against the new CRM services but I am having problems with the reflection component. 

    It would appear that the class attributes do not exist until they are populated.  If I try and use reflection against a populated attribute I can get the attribute type.  If it has not been populated I get a 'keynotfound' exception.

    The sample code below calls a referenced CRM webservice called 'Service'.

    Service.OrganizationServiceClient service = new Service.OrganizationServiceClient();
    Entity
    accnt = service.Retrieve("account", guid, columns);
    string
    propType = accnt[fieldName].GetType().Name;

    I have also tried the auto genration tool (CrmSvcUtil.exe) to create the object model locally and use reflection againt that.  I get the same result.

    Any ideas would be much appreciated.  I'd prefer not to have to hard code all the attribute types.  But with the limited time available for this integration it may be my only option, if I cannot resolve this reflection problem.

    Geordie

     

     
    Friday, August 26, 2011 10:57 PM

Answers

All replies

  • CRM will not return empty attributes. So first test with:

    if (accnt.Attributes.Contains("fieldname"))

    • Proposed as answer by Jan AS Saturday, August 27, 2011 10:46 AM
    Saturday, August 27, 2011 8:47 AM
  • Hi,

    You can get the type like this:

     

    string propType =  accnt[fieldName].GetType().ToString();
    

     

    // and then can compare with CRM types like this i.e. for a picklist:

    if (propType  == typeof(Picklist).ToString())

    {

     ///

    }

     


    Jehanzeb Javeed

    http://worldofdynamics.blogspot.com
    Linked-In Profile |CodePlex Profile

    If you find this post helpful then please "Vote as Helpful" and "Mark As Answer".
    Saturday, August 27, 2011 10:28 AM
  • With the code that I'm trying to replicate, I need to know the type before I can apply the correct code to populate the property.  Unfortunately I cannot determine the type unless it is populated...  That does not bode well for this upgrade!!

    Geordie 

    Saturday, August 27, 2011 12:40 PM
  • You could retrieve the metadata.
    • Proposed as answer by Jan AS Saturday, August 27, 2011 12:56 PM
    Saturday, August 27, 2011 12:41 PM
  • Hi Jehanzeb,

    If the field is not populated it does not matter if you call

    string propType =  accnt[fieldName].GetType().ToString();
    or
    string propType =  accnt[fieldName].GetType().Name;

    Both will fail with a 'keynotfound' exception.

    Geordie

    Saturday, August 27, 2011 12:44 PM
  • How do you do this?  Can you provide more details please.

    Thanks Geordie

    Saturday, August 27, 2011 12:45 PM
  • Hi,

    Yes you can then retrieve the entity metadata to determine before populating fields, can use the following code below to retrieve entity metadata via CRM Metadata services:

    RetrieveEntityResponse ts_ResponseRequest = null;
    

    ts_RetrieveRequest.LogicalName = "<entityname>";

    ts_RetrieveRequest.EntityItems = EntityItems.IncludeAttributes;

    ts_ResponseRequest = (RetrieveEntityResponse)crmMetadataService.Execute(ts_RetrieveRequest);

    You may also refer: 

     
    http://msdn.microsoft.com/en-us/library/bb955362.aspx

     


    Jehanzeb Javeed

    http://worldofdynamics.blogspot.com
    Linked-In Profile |CodePlex Profile

    If you find this post helpful then please "Vote as Helpful" and "Mark As Answer".
    • Proposed as answer by Jehanzeb.Javeed Saturday, August 27, 2011 12:50 PM
    • Marked as answer by Geordie_ca Thursday, September 1, 2011 1:37 PM
    Saturday, August 27, 2011 12:50 PM
  • Hi Jehanzeb,

    I tried your code and some variations I found when searching the Metadata service for CRM 2011 (http://crmvoyager.wordpress.com/2011/02/18/accessing-metadata-in-microsoft-crm-2011/).

    Unfortunatly I have hit another wall.  When I run the code below

     

    RetrieveEntityRequest request = new RetrieveEntityRequest();
    request.LogicalName =
    "account";
    request.EntityFilters =
    EntityFilters.Attributes;
    RetrieveAttributeResponse response = (RetrieveAttributeResponse)serviceProxy.Execute(request);
    string

    code = response.AttributeMetadata.AttributeType.Value.ToString();

    The Execute method is returning an invalid operation exception - 'Collection was modified; enumeration operation may not execute.'

    The CRM is being setup by a 3rd Party consulting company.  I'm starting to question if there are come problems with the way it is configured as I am also getting a NullReference exception when calling the retrieve method of the IOrganizationServiceProxy(http://social.microsoft.com/Forums/en-US/crmdevelopment/thread/17be3886-86ef-46f0-ba33-dd5d175bb755).

    I can pull account data back from CRM if I add a service using 'Add Service' create a OrganizationServiceClient object.  The retrieve and retrieveMultiple methods will then return account data.

    Service.

    OrganizationServiceClient service = new Service.OrganizationServiceClient

    ();
    EntityCollection

    result = service.RetrieveMultiple(query);

    Geordie

    Saturday, August 27, 2011 1:54 PM
  • You can not have a Attributeresponce on a entityrequest
    • Proposed as answer by Jan AS Saturday, August 27, 2011 3:00 PM
    Saturday, August 27, 2011 2:08 PM
  • Hi,

    Try using the following code:                           

    IOrganizationService jj_CrmService = null;
    

    jj_CrmService = GetCRMServiceObject("administrator", "password", "domain", "crm_organization_name", "http://Servername:port");        

    Entity jj_RetrievedEntity = null;

    RetrieveEntityRequest jj_EntityMetaDataRequest = new RetrieveEntityRequest();

    RetrieveEntityResponse jj_EntityMetaDataResponse = null;

    jj_EntityMetaDataRequest.EntityFilters = Microsoft.Xrm.Sdk.Metadata.EntityFilters.Attributes;

    jj_EntityMetaDataRequest.LogicalName = "account";

    jj_EntityMetaDataResponse = (RetrieveEntityResponse)jj_CrmService.Execute(jj_EntityMetaDataRequest);

    foreach (Microsoft.Xrm.Sdk.Metadata.AttributeMetadata jj_AttributeMetaData in jj_EntityMetaDataResponse.EntityMetadata.Attributes)

    {

           // your code

    }

     

    private IOrganizationService GetCRMServiceObject(string prmUserName, string prmPassword, string prmDomain, string prmOrgName, string prmServergUrl)

    {

                OrganizationServiceProxy jj_CrmServiceProxy = null;

                IOrganizationService jj_CrmService = null;

                ClientCredentials jj_ClientCredentials = new ClientCredentials();

                Uri jj_OrganizationUri = null;

                string jj_CRMServiceUrl = string.Empty;

                try

                {

                    jj_ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential(prmUserName, prmPassword, prmDomain);

                    jj_CRMServiceUrl = string.Concat(prmServergUrl, "/", prmOrgName, "/XRMServices/2011/Organization.svc");

                    jj_OrganizationUri = new Uri(jj_CRMServiceUrl);

                    jj_CrmServiceProxy = new OrganizationServiceProxy(jj_OrganizationUri, jj_OrganizationUri, jj_ClientCredentials, null);

                    jj_CrmService = (IOrganizationService)jj_CrmServiceProxy;

                }

                catch (System.Web.Services.Protocols.SoapException ex)

                {

                    throw new InvalidPluginExecutionException(ex.Detail.InnerText);

                }

                catch (Exception ex)

                {

                    throw new InvalidPluginExecutionException(ex.Message);

                }

                return jj_CrmService;

    }


    Jehanzeb Javeed

    http://worldofdynamics.blogspot.com
    Linked-In Profile |CodePlex Profile

    If you find this post helpful then please "Vote as Helpful" and "Mark As Answer".
    Saturday, August 27, 2011 2:15 PM
  • Hi Jehanzeb,

    I tried running your code and recieved the same error when it tried to run the Execute method.

    jj_EntityMetaDataResponse = (

    RetrieveEntityResponse

    )jj_CrmService.Execute(jj_EntityMetaDataRequest);

    InvalidOperation Exception: Collection was modified; enumeration operation may not execute.

    Geordie

     

    Saturday, August 27, 2011 2:43 PM
  • Hi,

    It seems like a problem with the CRM Metadata, try to publish all customization then restart CRM IIS Service (type iisreset) and try again. 


    Jehanzeb Javeed

    http://worldofdynamics.blogspot.com
    Linked-In Profile |CodePlex Profile

    If you find this post helpful then please "Vote as Helpful" and "Mark As Answer".
    Saturday, August 27, 2011 2:56 PM
  • I've tried restarting IIS but I get the same results.  I'll have to get the consultants to republish all customizations on Monday.  It will probably be worth restarting the whole server as well.

    Thanks for all your help.  I'll let you know how I get on on Monday!

    Geordie :-)

    Saturday, August 27, 2011 3:11 PM
  • Thanks again for everyones help on this issue.  Restarting IIS and the whole server has not resolved the problem.  At this point I suspect there is an issue with the installation of CRM or one of the subsequent customizations.  The consultants are about to create another environment so I will test against the new environment before any customizations have been applied.

    I'll post the results when I know more.

    Geordie

    Monday, August 29, 2011 10:44 PM
  • I have eventually sorted out why I have been getting these exceptions.  It was due to having a service reference to the CRM services in the same project as the early binding code.

    http://geekswithblogs.net/PsudoKnowledgeBase/archive/2011/09/01/nullreferenceexception-when-calling-the-retrieve-method-of-the-organizationserviceproxy-object.aspx

    Jehanzeb thanks for your help.

    Geordie

    • Marked as answer by Geordie_ca Thursday, September 1, 2011 1:36 PM
    Thursday, September 1, 2011 1:36 PM