CRM 2011 Organization Service Update() Failed inside Plugin - dynamics-crm-2011

I got this piece of code in my account plugin, which was working before, but keep having this wired issue now.
What it tries to do is, when the account is updated, also update the primary contact.
ColumnSet contactCols = new ColumnSet(new string[] { "firstname"});
Entity contact = orgService.Retrieve("contact", contactId, contactCols);
tracer.Trace("firstname is " + contact["firstname"]);
contact["firstname"] = DateTime.Now.ToString();
orgService.Update(contact);
The Retrieve() works, but the Update() will throw the following exception:
Unhandled Exception:
Microsoft.Xrm.Sdk.InvalidPluginExecutionException:
System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]:
System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]:
System.NullReferenceException:
Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #BF42D86C (Fault Detail is equal to Microsoft.Xrm.Sdk.OrganizationServiceFault). (Fault Detail is equal to Microsoft.Xrm.Sdk.OrganizationServiceFault).
at CRMSyncPlugin.SyncEntityClass.Execute(IServiceProvider serviceProvider)
at Microsoft.Crm.Asynchronous.V5ProxyPlugin.Execute(IServiceProvider serviceProvider)
at Microsoft.Crm.Asynchronous.EventOperation.InvokePlugin(AsyncExecutionContext context, IPlugin pluginInstance)
It said NullReferenceException, I just couldn't figure out what is null.
==========================================================
After trying what #Nicknow suggested, still the same error.
Here is what I got from the trace:
Retrieving Contact: 048f9564-81b4-e311-a27c-0026553e0f7c
Retrieved Contact
firstname is John
The retrieve worked, just the update failed. Thx

I've added some additional tracing and null checking, this should work:
tracer.trace("Retrieving Contact: {0}", contactId.ToString());
ColumnSet contactCols = new ColumnSet(new string[] { "firstname"});
Entity contact = orgService.Retrieve("contact", contactId, contactCols);
tracer.trace("Retrieved Contact");
tracer.Trace("firstname is " + contact.Attributes.Contains("firstname") ? contact["firstname"] : "(No Value for firstname)");
if (contact.Attributes.Contains("firstname")) contact["firstname"] = DateTime.Now.ToString();
else contact.Attributes.Add("firstname", DateTime.Now.ToString());
orgService.Update(contact);

You might check to see if there is another plugin that runs on the Update of Contact - the error could be coming from that other plugin instead of this one.

I generally don't try to update the object that I got from the Retrieve call. Just new up a Contact, set the ID, and include only the fields you're looking to change.
ColumnSet contactCols = new ColumnSet(new string[] { "firstname"});
Entity contact = orgService.Retrieve("contact", contactId, contactCols);
tracer.Trace("firstname is " + contact["firstname"]);
var updateContact = new Contact();
updateContact["contactId"] = contactId;
updateContact["firstname"] = DateTime.Now.ToString();
orgService.Update(updateContact);
I've found this tends to avoid these sorts of issues.

Related

Retrieve Current ID Crm Online

Entity title = new Entity();
title = service.Retrieve("incident",((Guid)((Entity)context.InputParameters["Target"]).Id), new ColumnSet("title"));
I am using this code to get the current id of an Incident while i'am closing it!
But received this error :
Unexpected exception from plug-in (Execute): FecharIncidente.Plugins.PostIncidenteClose: System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
One of my mates uses exactly the same code and is working on his crm !
Some help !?!
Apparently your InputParameters collection doesn't have a "Target" key value. Check that the request that you're using has a "Target" InputParameter.
if (context.InputParameters.Contains("Target") &&
context.InputParameters["Target"] is Entity)
{
// Obtain the target entity from the input parameters.
title = service.Retrieve("incident", ((Entity)context.InputParameters["Target"]).Id, new ColumnSet("title"));
Bet you "Target" in not Contained in InputParameters, resulting in KeyNotFoundException - "The given key was not present in the dictionary."
your can check for Target like Daryl explained or use the context available from the workflow rather like so ...
protected override void Execute(CodeActivityContext executionContext)
{
// Create the context
var context = executionContext.GetExtension<IWorkflowContext>();
var title = new Entity();
//context.PrimaryEntityName - should hold string incident
//context.PrimaryEntityId - should hold your guid
title = service.Retrieve(context.PrimaryEntityName, context.PrimaryEntityId, new ColumnSet("title"));
}

How to get id of saved entity

Dynamics CRM 2011 on premise
I can barely believe I can't find this out by Googling. MSDN is useless.
Here is some C# from a plugin:
integ_creditpayment creditpayment = new integ_creditpayment();
creditpayment.integ_Amount = totalPay;
//set more properties
context.AddObject(creditpayment);
context.SaveChanges();
Now I want to get the value of the id field in integ_creditpayment.
Can I get this immediately from creditpayment.id? (As in, does context.SaveChanges() cause the creditpayment variable to be updated with the new id?)
I'm assuming your real code is more complicated, but there is no need to use the context in your example code:
integ_creditpayment creditpayment = new integ_creditpayment();
creditpayment.integ_Amount = totalPay;
//set more properties
creditpayment.Id = service.Create(creditpayment);
You can also use a type initializer and get rid of your object all together if you'd like:
Guid id = service.Create(new integ_creditpayment
{
integ_Amount = totalPay;
});
service in this case is of type IOrganizationService
After the SaveChanges() you can get the record id with:
Guid justCreatedId = creditpayment.Id;

Get entity record values from Audit Details Response

Auditing of an entity is enabled,I want the entity record after deletion.So
I was trying to get that from audit entity records,like this:
RetrieveAuditDetailsRequest request = new RetrieveAuditDetailsRequest();
request.AuditId = _selectedId;
RetrieveAuditDetailsResponse response = (RetrieveAuditDetailsponse)_orgService.Execute(request);
EntityReference ObjectId = (EntityReference)response.AuditDetail.AuditRecord.Attributes["objectid"];
string ObjectName = ObjectId.LogicalName;
Guid Id = ObjectId.Id;
ColumnSet col = new ColumnSet(true);
Entity ent = _orgService.Retrieve(ObjectName,Id,col);
Its throwing an error "Expected non empty Guid".
FYI, I want this record values because I want to restore/recover record by creating it again.
Please help whats wrong with it??
You are attempting to retrieve the deleted record with this code:
string ObjectName = ObjectId.LogicalName;
Guid Id = ObjectId.Id;
ColumnSet col = new ColumnSet(true);
Entity ent = _orgService.Retrieve(ObjectName,Id,col);
This will fail with the error you are getting because no such record exists (it is deleted.) Unlike CRM 4 and earlier there are no soft deletes in 2011, once deleted it is gone from the database.
Replace it with the following code:
RetrieveRecordChangeHistoryRequest retrieveRequest = new RetrieveRecordChangeHistoryRequest();
changeRequest.Target = new EntityReference(ObjectName, Id);
RetrieveRecordChangeHistoryResponse response =
(RetrieveRecordChangeHistoryResponse)_orgService.Execute(retrieveRequest);
if (response.AuditDetailCollection != null)
{
var auditDetails = response.AuditDetailCollection;
// Do work
}
You then enumerate through the auditDetails to get the correct attributes.
You can find more at http://blogs.msdn.com/b/crm/archive/2011/05/23/recover-your-deleted-crm-data-and-recreate-them-using-crm-api.aspx.
The "Expected non empty Guid" error is thrown whenever you try to retrieve something with an empty GUID (Guid.Empty, 00000000-0000-0000-0000-000000000000). I'm guessing your _selectedId is not set to an actual GUID. Maybe you're setting it from a Nullable GUID and you are calling ValueOrDefault(), which is resulting in it getting set to the empty Guid, and failing in your Request?

Update child entity / Attach entity to context

I am creating a pre event plugin for CRM 2011 that sets the account owner and updates all the child contacts with the same owner. The plugin is installed correctly and updates the main account record correctly but the child contact owner does not change . I have pushed the owner name into another field of the contact to check I have the correct details and that field is updating.
I'm sure its something to do with attaching the child contacts to the correct context but so far I have drawn a blank.
//Set new account owner - Works fine
account.OwnerId = new EntityReference(SystemUser.EntityLogicalName, ownerId);
//Pass the same owner into the contacts - Does not get updated
UpdateContacts(account.Id, ownerId, service, tracingService);
The system is successfully updating the account owner and the description label of the child record.
public static void UpdateContacts(Guid parentCustomerId, Guid ownerId, IOrganizationService service, ITracingService tracingService)
{
// Create the FilterExpression.
FilterExpression filter = new FilterExpression();
// Set the properties of the filter.
filter.FilterOperator = LogicalOperator.And;
filter.AddCondition(new ConditionExpression("parentcustomerid", ConditionOperator.Equal, parentCustomerId));
// Create the QueryExpression object.
QueryExpression query = new QueryExpression();
// Set the properties of the QueryExpression object.
query.EntityName = Contact.EntityLogicalName;
query.ColumnSet = new ColumnSet(true);
query.Criteria = filter;
// Retrieve the contacts.
EntityCollection results = service.RetrieveMultiple(query);
tracingService.Trace("Results : " + results.Entities.Count);
SystemUser systemUser = (SystemUser)service.Retrieve(SystemUser.EntityLogicalName, ownerId, new ColumnSet(true));
tracingService.Trace("System User : " + systemUser.FullName);
XrmServiceContext xrmServiceContext = new XrmServiceContext(service);
for (int i = 0; i < results.Entities.Count; i++)
{
Contact contact = (Contact)results.Entities[i];
contact.OwnerId = new EntityReference(SystemUser.EntityLogicalName, systemUser.Id);
contact.Description = systemUser.FullName;
xrmServiceContext.Attach(contact);
xrmServiceContext.UpdateObject(contact);
xrmServiceContext.SaveChanges();
tracingService.Trace("Updating : " + contact.FullName);
}
}
The tracing service prints out everything I would expect. Do I need to also attach the system user and somehow attach the entity reference to the context?
Any help appreciated.
You have to make a separate web service call using AssignRequest to change the ownership of a record. Unfortunately you cannot just change the Owner attribute.
I think I was getting myself into all sorts of mess with this plugin as by default changing the account owner automatically changes the associated contacts owner. I was therefore trying to overwrite something that it was already doing.
By using the AssignRequest to set the account owner rather than the child records it worked fine. Credit given to Chris as he pointed me in the right direction.
All that was needed was to change the first line of my code to use AssignRequest and the entire UpdateContacts method became obselete.

CRM 2011 KeyNotFoundException exception

I am new to CRM development.
I have a Custom Entity "customer". This Entity has a Field called "defaultcustomer", which can be TRUE or FALSE. I am working on a Plug-In where i need to set the "defaultcustomer" to FALSE for all the "Customers". I am doing it as below:
FACTS:
I have registered the plugin for the entity "customer" itself. So when the Entity "customer" is updated, the plugin fires.
private void MakeAllNonDefault()
{
try
{
QueryExpression query = new QueryExpression("customer");
query.ColumnSet = new ColumnSet("defaultcustomer");
EntityCollection retrieved = service.RetrieveMultiple(query);
foreach (Entity myCustomer in retrieved.Entities)
{
myCustomer["defaultcustomer"] = false;
service.Update(myCustomer);
}
}
catch (Exception ex)
{
throw new InvalidPluginExecutionException("An error occurred in MakeAllNonDefault(): " + ex.ToString());
}
}
ERROR:
It throws error on this line:
myCustomer["defaultcustomer"] = false;
System.Collections.Generic.KeyNotFoundException:
The given key was not present in the dictionary.
The error means that particular field is not present in the collection of properties. In CRM, only properties that have been set or updated are included.
Try something like:
foreach (Entity myCustomer in retrieved.Entities)
{
if (myCustomer.Attributes.ContainsKey("defaultcustomer"))
{
myCustomer["defaultcustomer"] = false;
}
else
{
myCustomer.Attributes.Add("defaultcustomer", false);
}
service.Update(myCustomer);
}
Have you double checked that the field really is called defaultcustomer?
If it's a custom entity then it's likely the field begins with a prefix, for instance new_defaultcustomer. Make sure you are using the name of the field, not the display name.
The solution posted by #glosrob seems fine. Are you still getting "The given key was not present in the dictionary"?
Try to use ITracingService to get more information about the plugin execution flow.
While Update all Crm fields are False accept that what you Update the field. For that you can use Pre/Post Images in Plugin. you will found that crm field key and update what you need.

Resources