locked
How to retrieve custom attributes from a crm plugin RRS feed

  • Question

  • Hi,

    I am creating a plugin to retrieve the appointment scheduled time and update the last meeting (custom attribute) of each atttendees once the appointment has been completed.

    With a plugin( using the crm dlls), i don't have access to the custom attribute.

    I added the crm webservices but then the retrieve method is messed up.

    Is there a way to access custom attributes through a plugin?

    Thanks,

    Brightlin
    Wednesday, March 17, 2010 8:37 PM

Answers

  • Hah, it's a copy/paste typo.

    entity.Properties[LAST_MEETING] = spLastMeeting;
    

    should be changed to:

    entity.Properties.Add(new CrmDateTimeProperty(LAST_MEETING, new CrmDateTime(cdtStartTime.Value))); 

    as I have previously pointed out.


    Daniel Cai | http://danielcai.blogspot.com
    Wednesday, March 24, 2010 3:45 PM

All replies

  • use Dynamic entity when retriving the data..

    select return dynamic entities to be true...

    // Retrieve the contact.

     

    RetrieveMultipleRequest req = new RetrieveMultipleRequest();

    req.Query = query;

    req.ReturnDynamicEntities =

    true;

     

    RetrieveMultipleResponse res

    = (

    RetrieveMultipleResponse)myService.Execute(req);



    Please read following article for the same

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

    Wednesday, March 17, 2010 9:10 PM
  • I'm not sure I'm following you.

    Wednesday, March 17, 2010 9:26 PM
  • you must be retriving the data using query expression in your entity..(something like following code)..this will return dynamic entity..


    now assume "OrderCreated" in custom boolen filed you can get this details using following code..

    if (dynamicContract.Properties.Contains("ordercreated"))

    {

    Boolean isReadyForOrderCreation =

    Convert.ToBoolean(((CrmBoolean)dynamicContract.Properties["ordercreated"]).Value);

    }

     

     


    Hope this helps..



    /// <summary>
    		/// Retrieves the Account objects
    		/// </summary>
    		/// <param name="myService">The CRM Service</param>
    		/// <param name="searchId">The Search Id String</param>
    		/// <returns>Account Object</returns>
    		private DynamicEntity RetrieveDynamicEntityForContract(ICrmService myService, string contractid)
    		{
    			DynamicEntity myDynamicEntity = null;
    			try
    			{
    
    				QueryExpression query = new QueryExpression();
    				query.ColumnSet = new AllColumns(); 
    				
    
    
    				query.EntityName = EntityName.contract.ToString();
    				FilterExpression filter = new FilterExpression();
    				query.Criteria = filter;
    
    				ConditionExpression hasAccountNoOf = new ConditionExpression();
    				filter.Conditions.Add(hasAccountNoOf);
    
    				hasAccountNoOf.AttributeName = "contractid";
    				hasAccountNoOf.Operator = ConditionOperator.Equal;
    				hasAccountNoOf.Values = new string[] { contractid };
    
    
    				// Retrieve the contact.
    				RetrieveMultipleRequest req = new RetrieveMultipleRequest();
    				req.Query = query;
    				req.ReturnDynamicEntities = true;
    
    				RetrieveMultipleResponse res
    				   = (RetrieveMultipleResponse)myService.Execute(req);
    
    				if (res.BusinessEntityCollection.BusinessEntities.Count == 1)
    				{
    
    					foreach (BusinessEntity be in res.BusinessEntityCollection.BusinessEntities)
    					{
    						myDynamicEntity = (DynamicEntity)be;
    						break;
    					}
    				}
    
    
    			}
    			catch (Exception ex)
    			{
    				//throw (ex);
    			}
    			return myDynamicEntity;
    
    		}
    

    Wednesday, March 17, 2010 9:43 PM
  • try like that

    private CrmService CreateCrmService(IPluginExecutionContext context)
            {

                CrmAuthenticationToken myToken = new CrmAuthenticationToken();
                myToken.AuthenticationType = 0;
                myToken.CallerId = context.UserId;
                myToken.OrganizationName = context.OrganizationName;

                Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\MSCRM");

                CrmService childCrmService = new CrmService();
                childCrmService.Url = String.Concat(regkey.GetValue("ServerUrl").ToString(), "/2007/crmservice.asmx");

                childCrmService.CrmAuthenticationTokenValue = myToken;
                childCrmService.UseDefaultCredentials = true;

                childCrmService.CorrelationTokenValue = new CorrelationToken(context.CorrelationId, context.Depth, context.CorrelationUpdatedTime);
                return childCrmService;
            }


                           DynamicEntity entity = (DynamicEntity)context.InputParameters.Properties["Target"];

                            TargetRetrieveDynamic targetIncidentEntity = new TargetRetrieveDynamic();
                            targetIncidentEntity.EntityId = ((Key)entity.Properties["Entityid"]).Value;
                            targetIncidentEntity.EntityName = EntityName.incident.ToString();

                            RetrieveRequest retrieveRequest = new RetrieveRequest();
                            retrieveRequest.ColumnSet = new Microsoft.Crm.Sdk.Query.AllColumns();
                            retrieveRequest.ReturnDynamicEntities = true;
                            retrieveRequest.Target = targetIncidentEntity;

                            CrmService crmService = (CrmService)CreateCrmService(context);
                            RetrieveResponse retrieveResponse = (RetrieveResponse)crmService.Execute(retrieveRequest);

                            DynamicEntity retrievedEntity = null;
                            retrievedEntity = (DynamicEntity)retrieveResponse.BusinessEntity;


    Or you can use

    ICrmService crmService = context.CreateCrmService(false);
    DynamicEntity currentEntity =(MyEntityName )service.Retrieve("MyEntityName ", currentEntityID, new AllColumns());

    ,but that is not always working (skd setting post,pre,child,parent,etc. does matter)


    Mariusz
    Wednesday, March 17, 2010 9:47 PM
  • Hi Brightlin

    Use crm dll or Webservice, any one of there.
    If you are using both of these there may arise ambiguity in methods and reference. In that condition you can use namespace to differentiate them

    You can retrieve needed fields using TargetRetrieveDynamic.

    //variable initialization    
    TargetRetrieveDynamic target = new TargetRetrieveDynamic();        
    RetrieveRequest retrieveRequest = new RetrieveRequest();           
    RetrieveResponse retrieveResponse = null;                                      
    DynamicEntity entity = null;                                     
    target.EntityName = <name of entity here>;
    target.EntityId = <guid of entity here>;

    //initialize request parameters
    retrieveRequest.ColumnSet = new AllColumns(); // all coulums will be retrieved.
    retrieveRequest.ReturnDynamicEntities = true;
    retrieveRequest.Target = target;

    //build the response object
    retrieveResponse = (RetrieveResponse)GetCrmService().Execute(retrieveRequest);

    //retrieve the service order item from the response
    entity = (DynamicEntity)retrieveResponse.BusinessEntity;

    Regards
    Vinoth

    Thursday, March 18, 2010 6:14 AM
  • Hi Vinoth,

    I have tried that but "entity" doesn't contain custom attributes. I have checked it by attaching to process.

    Is there something I need do?

    But I actually get the following message "Value of type 'CrmDateTimeProperty' is not supported. Parameter Name: value"

    Here's my code:

     

                   ICrmService crmService = context.CreateCrmService(true);

                   Guid guidAppointment = monikerEntityInput.Id; //(Guid)context.InputParameters.Properties[ParameterName.Id];
                    appointment oAppointment = (appointment)crmService.Retrieve(CrmSdk.EntityName.appointment.ToString(), guidAppointment, new AllColumns());

                    // 2. Retrieve the Appointment start time
                    CrmDateTime cdtStartTime = oAppointment.scheduledstart;

                    TargetRetrieveDynamic retrieveDynamic = new TargetRetrieveDynamic();
                    TargetUpdateDynamic updateDynamic = new TargetUpdateDynamic();
                    RetrieveRequest retrieveRequest = new RetrieveRequest();
                    UpdateRequest updateRequest = new UpdateRequest();
                    RetrieveResponse retrieveResponse = new RetrieveResponse();
                    UpdateResponse updateResponse = new UpdateResponse();
                    DynamicEntity entity = null;
                    CrmDateTimeProperty spLastMeeting = new CrmDateTimeProperty();

           


                    spLastMeeting.Name = LAST_MEETING; //= (CrmDateTimeProperty)entity.Properties[LAST_MEETING];
                    spLastMeeting.Value = new CrmDateTime(); //cdtStartTime.Value;
                    spLastMeeting.Value.Value = cdtStartTime.Value;

                    foreach (activityparty apRequiredAttendee in oAppointment.requiredattendees)
                    {

                        if (apRequiredAttendee.partyid.type == EntityName.contact.ToString())
                        {

                            retrieveDynamic.EntityName = EntityName.contact.ToString();
                            retrieveDynamic.EntityId = apRequiredAttendee.partyid.Value;

                            retrieveRequest.ColumnSet = new AllColumns();
                            retrieveRequest.ReturnDynamicEntities = true;
                            retrieveRequest.Target = retrieveDynamic;

                            retrieveResponse = (RetrieveResponse)crmService.Execute(retrieveRequest);

                            entity = (DynamicEntity)retrieveResponse.BusinessEntity;
                           

                            entity.Properties[LAST_MEETING] = spLastMeeting;
      

                            updateDynamic.Entity = entity;

                            updateRequest.Target = updateDynamic;

                            updateResponse = (UpdateResponse)crmService.Execute(updateRequest);


                        }
                    }
                }

    Friday, March 19, 2010 4:17 PM
  • What if you use the following code?

        entity.Properties.Add(new CrmDateTimeProperty(LAST_MEETING, new CrmDateTime(cdtStartTime.Value)));
    

    To replace

        entity.Properties[LAST_MEETING] = spLastMeeting;
    

    Daniel Cai | http://danielcai.blogspot.com
    Friday, March 19, 2010 7:35 PM
  • I get the following error:

    One or more of the option values for this picklist are not in the range of allowed values.

    Do i need to remove that property, update, then add it and update again

                            entity.Properties.Remove(LAST_MEETING);

                            updateDynamic.Entity = entity;

                            updateRequest.Target = updateDynamic;

                            updateResponse = (UpdateResponse)crmService.Execute(updateRequest);

     

                           entity.Properties.Add(new CrmDateTimeProperty(LAST_MEETING, new CrmDateTime(cdtStartTime.Value)));

                            updateDynamic.Entity = entity;

                            updateRequest.Target = updateDynamic;

                            updateResponse = (UpdateResponse)crmService.Execute(updateRequest);

    Something like that?

    Friday, March 19, 2010 9:20 PM
  • Try to replace the following line

    retrieveRequest.ColumnSet = new AllColumns();
    

    with

    retrieveRequest.ColumnSet = new ColumnSet(new string[] { "contactid" });

    And see if it works.

    The principle behind this is only retrieve what you need, the same is true when you do the update.

     Hope this helps.


    Daniel Cai | http://danielcai.blogspot.com
    Friday, March 19, 2010 11:23 PM
  • On a second thought, why you even need to retrieve the contact record if you are just updating one single attribute that you already knew the value? 

    Your code in the loop could be as simple as this: 

     

                if (apRequiredAttendee.partyid.type == EntityName.contact.ToString())
                {
                    entity = new DynamicEntity(EntityName.contact.ToString());                      
                    entity.Properties.Add(new KeyProperty("contactid", new Key(apRequiredAttendee.partyid.Value));  
                    entity.Properties.Add(new CrmDateTimeProperty(LAST_MEETING, new CrmDateTime(cdtStartTime.Value)));  
    
                    updateDynamic.Entity = entity;
                    updateRequest.Target = updateDynamic;
                    updateResponse = (UpdateResponse)crmService.Execute(updateRequest);
    
                }
    The number of your CRM service calls has been reduced to half. Hope this helps. 

     


    Daniel Cai | http://danielcai.blogspot.com
    Saturday, March 20, 2010 5:25 AM
  • Thanks Daniel.

    It works now!!

    Cheers!

    Brightlin

    Monday, March 22, 2010 6:31 PM
  • I realize that I need to retrieve the custom field to validate the date before updating it. To validate that I am not updating the contact with an appointment that's before an exisiting date.

    I am still stuck.

    Monday, March 22, 2010 9:02 PM
  • In this case, your code should be like this: 

     

                DateTime startTime = Convert.ToDateTime(cdtStartTime.Value);
    
                foreach (activityparty apRequiredAttendee in oAppointment.requiredattendees)
                {
                    if (apRequiredAttendee.partyid.type == EntityName.contact.ToString())
                    {
                        retrieveDynamic.EntityName = EntityName.contact.ToString();
                        retrieveDynamic.EntityId = apRequiredAttendee.partyid.Value;
    
                        retrieveRequest.ColumnSet = new ColumnSet(new string[] { "contactid", LAST_MEETING });
                        retrieveRequest.ReturnDynamicEntities = true;
                        retrieveRequest.Target = retrieveDynamic;
    
                        retrieveResponse = (RetrieveResponse)crmService.Execute(retrieveRequest);
                        entity = (DynamicEntity)retrieveResponse.BusinessEntity;
    
                        if (!entity.Properties.Contains(LAST_MEETING))
                            continue;
    
                        DateTime lastMeeting = Convert.ToDateTime(((CrmDateTime)entity.Properties[LAST_MEETING]).Value);
                        if (startTime <= lastMeeting)
                            continue;
    
                        entity.Properties.Add(new CrmDateTimeProperty(LAST_MEETING, new CrmDateTime(cdtStartTime.Value)));
    
                        updateDynamic.Entity = entity;
                        updateRequest.Target = updateDynamic;
                        updateResponse = (UpdateResponse)crmService.Execute(updateRequest);
                    }
                }
    Hope you get the point. 

     


    Daniel Cai | http://danielcai.blogspot.com
    Tuesday, March 23, 2010 2:13 AM
  • On this line:

    DateTime lastMeeting = Convert.ToDateTime(((CrmDateTimeProperty)entity.Properties[LAST_MEETING]).Value.Value);

    I'm getting "Unable to cast object of type 'Microsoft.Crm.Sdk.CrmDateTime' to type 'Microsoft.Crm.Sdk.CrmDateTimeProperty' error message.

    The actual Field "LAST_MEETING" is of type datetime.

     

    Wednesday, March 24, 2010 3:05 PM
  • Hmm, then the line of code should be:

                DateTime lastMeeting = Convert.ToDateTime(((CrmDateTime)entity.Properties[LAST_MEETING]).Value);
    

    It shouldn't be hard to figure that out with the help Visual Studio environment. Hope this has helped.


    Daniel Cai | http://danielcai.blogspot.com
    Wednesday, March 24, 2010 3:16 PM
  • that's is the first thing I tried that but if fails on the update:

    updateResponse = (UpdateResponse)crmService.Execute(updateRequest);

    {"Value of type 'CrmDateTimeProperty' is not supported.\r\nParameter name: value"}

    It's weird

    Wednesday, March 24, 2010 3:37 PM
  • Hah, it's a copy/paste typo.

    entity.Properties[LAST_MEETING] = spLastMeeting;
    

    should be changed to:

    entity.Properties.Add(new CrmDateTimeProperty(LAST_MEETING, new CrmDateTime(cdtStartTime.Value))); 

    as I have previously pointed out.


    Daniel Cai | http://danielcai.blogspot.com
    Wednesday, March 24, 2010 3:45 PM
  • Thanks alot Daniel for your help. Much appreciated!
    Wednesday, March 24, 2010 6:16 PM
  • Glad to know that I have helped. I am proposing to close this thread. 

    Cheers.


    Daniel Cai | http://danielcai.blogspot.com
    Wednesday, March 24, 2010 6:32 PM