Solved

CRM Callout - Phonecall Can't Update (The object can not be updated because it is read-only)

Posted on 2008-06-18
7
1,522 Views
Last Modified: 2009-07-30
Hi Experts,

I am trying to update the Sender fields of a phonecall. Essentially, what I am trying to achieve is: When an Account is transfered to a new user, the Contacts and Activities  are transfered to that user to. Unfortunately, the Sender field in the Activity remains in the old ower's name and therefore still appears in their "My Activities". I wrote this callout to drill down through the Acctount=>Contact=>Activities and update the Activities Sender fields. The callout fails with an error code "8004022e" and error message "The object can not be updated because it is read-only because it is read-only".  

Any ideas,

Matt
/*

 * File:		Sender.cs

 * Author:		Matt Skelton

 * Date:		June 11, 2008		: Created

 *				June 16, 2008		: Upated

 * 

 * Description:	This class is fired before an Account (Facility)

 *				is assigned from one user to another user. 

 *				It drills down from the entity to all of its 

 *				Activities (Phonecalls, Letters, Faxes, Emails)

 *				and assigns the Sender field the value of the new user.

 * 

 *				This is needed to remove the Activities from the

 *				old user's My Activities view.

 */
 

//Error

//Server was unable to process request..

//0x8004022e

//The object cannot be updated because it is read-only.
 

using System;

using System.Collections;

using Microsoft.Crm.Callout;

using ChangeSenderOnTransfer;

using ChangeSenderOnTransfer.brodacrm;

using System.IO;

using System.Xml;

using System.Xml.Serialization;
 

namespace ChangeSenderOnTransfer

{

	/// <summary>

	/// Summary description for Sender.

	/// </summary>

	public class Sender : CrmCalloutBase

	{

		private CrmService service;

		private Guid assignedToId;

		private ArrayList contactList	= new ArrayList();

		private ArrayList phonecallList = new ArrayList();

		private ArrayList letterList	= new ArrayList();

		private ArrayList emailList		= new ArrayList();

		private ArrayList faxList		= new ArrayList();

		

		public override void PostAssign(CalloutUserContext userContext, CalloutEntityContext entityContext,

			string preImageEntityXml, string postImageEntityXml)

		{

			// Set up the CrmService

			service								= new CrmService();

			service.Url							= "http://brodacrm:5555/mscrmservices/2006/crmservice.asmx";

			service.CallerIdValue				= new CallerId();

			service.CallerIdValue.CallerGuid	= new Guid("A016F63C-4370-DC11-85F6-001372F8A7FD");

			service.Credentials					= System.Net.CredentialCache.DefaultCredentials;
 

			System.Xml.XmlDocument postImageEntity = new XmlDocument();

			postImageEntity.LoadXml(postImageEntityXml);
 

			foreach (XmlElement element in postImageEntity.GetElementsByTagName("Property"))

			{

				string elementName = element.Attributes.GetNamedItem("Name").Value;
 

				switch(elementName)

				{

					case "ownerid":
 

						assignedToId = new Guid(element.FirstChild.InnerText);
 

						break;

				}

			}

			

			switch (entityContext.EntityTypeCode)

			{

				//Account

				case 1:

					

					contactList = RetrieveContactsForAccount(entityContext.InstanceId);

					

					foreach (contact contact in contactList)

					{

						ClearLists();
 

						phonecallList	= RetrievePhonecallsForContact(contact.contactid.Value);

						letterList		= RetrieveLettersForContact(contact.contactid.Value);

						emailList		= RetrieveEmailsForContact(contact.contactid.Value);

						faxList			= RetrieveFaxesForContact(contact.contactid.Value);
 

						try

						{

							if (IsValidGuid(assignedToId.ToString()))

							{

								UpdateActivities(assignedToId);

							}

							else

							{

								throw new Exception("assignedToId != Valid Guid");

							}

						}

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

						{

							TextWriter log = TextWriter.Synchronized(File.AppendText(@"C:\CRM_SDK_Drop\Assign.txt"));

							log.WriteLine("Error");

							log.WriteLine(ex.Message + "." + ex.Detail.InnerText);

							log.WriteLine();

							log.Close();

						}

						catch(Exception ex)

						{

							TextWriter log = TextWriter.Synchronized(File.AppendText(@"C:\CRM_SDK_Drop\Assign.txt"));

							log.WriteLine("Error");

							log.WriteLine(ex.Message);

							log.WriteLine();

							log.Close();

						}

					}

	

					break;

			}

		}
 

		#region Helper Methods
 

		/// <summary>

		/// Returns true if argument is valid Guid

		/// </summary>

		/// <param name="guidCandidate"></param>

		/// <returns></returns>

		private bool IsValidGuid(string testGuid)

		{

			bool isValidGuid	= false;

			

			try

			{

				Guid guid		= new Guid(testGuid);

				isValidGuid		= true;

			}

			catch (Exception)

			{

				//

			}

			

			return isValidGuid;

		}

		

		/// <summary>

		/// Updates Phonecall, Email, Letter, and Fax activies

		/// </summary>

		private void UpdateActivities(Guid assignedToId)

		{

			foreach (phonecall phonecall in phonecallList)

			{

				UpdatePhonecall(phonecall.activityid.Value, assignedToId);

			}
 

			foreach (letter letter in letterList)

			{

				UpdateLetter(letter.activityid.Value, assignedToId);

			}
 

			foreach (email email in emailList)

			{

				UpdateEmail(email.activityid.Value, assignedToId);

			}
 

			foreach (fax fax in faxList)

			{

				UpdateEmail(fax.activityid.Value, assignedToId);

			}

		}

		

		/// <summary>

		/// Clears ArrayLists

		/// </summary>

		private void ClearLists()

		{

			phonecallList.Clear();

			letterList.Clear();

			emailList.Clear();

			faxList.Clear();

		}
 

		/// <summary>

		/// Updates a Phonecall's From/Sender field to a new UserId

		/// </summary>

		/// <param name="phonecallId"></param>

		private void UpdatePhonecall(Guid phonecallId, Guid systemUserId)

		{		

			phonecall phonecall					= new phonecall();

			activityparty from				= new activityparty();

			from.partyid						= new Lookup();

			from.partyid.type					= EntityName.systemuser.ToString();

			from.partyid.Value					= systemUserId;

			phonecall.from						= new activityparty[] {from};

			phonecall.activityid				= new Key();

			phonecall.activityid.Value			= phonecallId; 

			service.Update(phonecall);

		}
 

		/// <summary>

		/// Updates a Letter's From/Sender field to a new UserId

		/// </summary>

		/// <param name="letterId"></param>

		private void UpdateLetter(Guid letterId, Guid systemUserId)

		{

			letter letter						= new letter();

			letter.activityid					= new Key();

			letter.activityid.Value				= letterId;

			activityparty from					= new activityparty();

			from.partyid						= new Lookup();

			from.partyid.type					= EntityName.systemuser.ToString();

			from.partyid.Value					= systemUserId;

			letter.from							= new activityparty[] {from}; 

			service.Update(letter);

		}
 

		/// <summary>

		/// Updates an Email's From/Sender field to a new UserId

		/// </summary>

		/// <param name="emailId"></param>

		private void UpdateEmail(Guid emailId, Guid systemUserId)

		{

			email email							= new email();

			email.activityid					= new Key();

			email.activityid.Value				= emailId;

			activityparty from					= new activityparty();

			from.partyid						= new Lookup();

			from.partyid.type					= EntityName.systemuser.ToString();

			from.partyid.Value					= systemUserId;

			email.from							= new activityparty[] {from}; 

			service.Update(email);

		}
 

		/// <summary>

		/// Updates an Fax's From/Sender field to a new UserId

		/// </summary>

		/// <param name="emailId"></param>

		private void UpdateFax(Guid faxId, Guid systemUserId)

		{

			fax fax								= new fax();

			fax.activityid						= new Key();

			fax.activityid.Value				= faxId;

			activityparty from					= new activityparty();

			from.partyid						= new Lookup();

			from.partyid.type					= EntityName.systemuser.ToString();

			from.partyid.Value					= systemUserId;

			fax.from							= new activityparty[] {from}; 

			service.Update(fax);

		}
 

		/// <summary>

		/// Retrieves all Contacts for an Account

		/// </summary>

		/// <param name="accountId"></param>

		/// <returns></returns>

		private ArrayList RetrieveContactsForAccount(Guid accountId)

		{

			ColumnSet columnSet					= new ColumnSet();

			columnSet.Attributes				= new string[] {"contactid"};

							

			ConditionExpression condition1		= new ConditionExpression();

			condition1.AttributeName			= "parentcustomerid";

			condition1.Operator					= ConditionOperator.Equal;

			condition1.Values					= new string [] {accountId.ToString()};

														

			FilterExpression filter				= new FilterExpression();

			filter.FilterOperator				= LogicalOperator.And;

			filter.Conditions					= new ConditionExpression[] {condition1};

						

			QueryExpression query				= new QueryExpression();

			query.EntityName					= EntityName.contact.ToString();

			query.ColumnSet						= columnSet;

			query.Criteria						= filter;

							

			BusinessEntityCollection contacts	= service.RetrieveMultiple(query);
 

			ArrayList contactList				= new ArrayList();

						

			if (contacts != null)

			{

				if (contacts.BusinessEntities.Length > 0)

				{

					foreach (object businessEntity in contacts.BusinessEntities)

					{

						contact contact	= (contact)businessEntity;
 

						contactList.Add(contact);

					}

				}

			}
 

			return contactList;

		}
 

		/// <summary>

		/// Populates the phonecallList with Phonecalls for a Contact

		/// </summary>

		/// <param name="contactId"></param>

		/// <returns></returns>

		private ArrayList RetrievePhonecallsForContact(Guid contactId)

		{

			ColumnSet columnSet					= new ColumnSet();

			columnSet.Attributes				= new string[] {"from", "activityid"};

							

			ConditionExpression condition1		= new ConditionExpression();

			condition1.AttributeName			= "regardingobjectid";

			condition1.Operator					= ConditionOperator.Equal;

			condition1.Values					= new string [] {contactId.ToString()};

														

			FilterExpression filter				= new FilterExpression();

			filter.FilterOperator				= LogicalOperator.And;

			filter.Conditions					= new ConditionExpression[] {condition1};

						

			QueryExpression query				= new QueryExpression();

			query.EntityName					= EntityName.phonecall.ToString();

			query.ColumnSet						= columnSet;

			query.Criteria						= filter;

							

			BusinessEntityCollection phonecalls	= service.RetrieveMultiple(query);

			

			ArrayList phonecallList				= new ArrayList();	

		

			if (phonecalls != null)

			{

				if (phonecalls.BusinessEntities.Length > 0)

				{

					foreach (object businessEntity in phonecalls.BusinessEntities)

					{

						phonecall phonecall	= (phonecall)businessEntity;
 

						phonecallList.Add(phonecall);

					}

				}

			}
 

			return phonecallList;

		}
 

		/// <summary>

		/// Populates the letterList with Letters for a Contact

		/// </summary>

		/// <param name="contactId"></param>

		/// <returns></returns>

		private ArrayList RetrieveLettersForContact(Guid contactId)

		{

			ColumnSet columnSet					= new ColumnSet();

			columnSet.Attributes				= new string[] {"from", "activityid"};

							

			ConditionExpression condition1		= new ConditionExpression();

			condition1.AttributeName			= "regardingobjectid";

			condition1.Operator					= ConditionOperator.Equal;

			condition1.Values					= new string [] {contactId.ToString()};

														

			FilterExpression filter				= new FilterExpression();

			filter.FilterOperator				= LogicalOperator.And;

			filter.Conditions					= new ConditionExpression[] {condition1};

						

			QueryExpression query				= new QueryExpression();

			query.EntityName					= EntityName.letter.ToString();

			query.ColumnSet						= columnSet;

			query.Criteria						= filter;

							

			BusinessEntityCollection letters	= service.RetrieveMultiple(query);

					

			ArrayList letterList				= new ArrayList();	
 

			if (letters != null)

			{

				if (letters.BusinessEntities.Length > 0)

				{

					foreach (object businessEntity in letters.BusinessEntities)

					{

						letter letter = (letter)businessEntity;
 

						letterList.Add(letter);

					}

				}

			}
 

			return letterList;

		}
 

		/// <summary>

		/// Populates the emailList with Emails for a Contact

		/// </summary>

		/// <param name="contactId"></param>

		/// <returns></returns>

		private ArrayList RetrieveEmailsForContact(Guid contactId)

		{

			ColumnSet columnSet					= new ColumnSet();

			columnSet.Attributes				= new string[] {"from", "activityid"};

							

			ConditionExpression condition1		= new ConditionExpression();

			condition1.AttributeName			= "regardingobjectid";

			condition1.Operator					= ConditionOperator.Equal;

			condition1.Values					= new string [] {contactId.ToString()};

														

			FilterExpression filter				= new FilterExpression();

			filter.FilterOperator				= LogicalOperator.And;

			filter.Conditions					= new ConditionExpression[] {condition1};

						

			QueryExpression query				= new QueryExpression();

			query.EntityName					= EntityName.email.ToString();

			query.ColumnSet						= columnSet;

			query.Criteria						= filter;

							

			BusinessEntityCollection emails		= service.RetrieveMultiple(query);

						

			ArrayList emailList					= new ArrayList();	
 

			if (emails != null)

			{

				if (emails.BusinessEntities.Length > 0)

				{

					foreach (object businessEntity in emails.BusinessEntities)

					{

						email email = (email)businessEntity;
 

						emailList.Add(email);

					}

				}

			}
 

			return emailList;

		}
 

		/// <summary>

		/// Populates the faxList with Faxes for a Contact

		/// </summary>

		/// <param name="contactId"></param>

		/// <returns></returns>

		private ArrayList RetrieveFaxesForContact(Guid contactId)

		{

			ColumnSet columnSet					= new ColumnSet();

			columnSet.Attributes				= new string[] {"from", "activityid"};

							

			ConditionExpression condition1		= new ConditionExpression();

			condition1.AttributeName			= "regardingobjectid";

			condition1.Operator					= ConditionOperator.Equal;

			condition1.Values					= new string [] {contactId.ToString()};

														

			FilterExpression filter				= new FilterExpression();

			filter.FilterOperator				= LogicalOperator.And;

			filter.Conditions					= new ConditionExpression[] {condition1};

						

			QueryExpression query				= new QueryExpression();

			query.EntityName					= EntityName.fax.ToString();

			query.ColumnSet						= columnSet;

			query.Criteria						= filter;

							

			BusinessEntityCollection faxes		= service.RetrieveMultiple(query);

						

			ArrayList faxList					= new ArrayList();	
 

			if (faxes != null)

			{

				if (faxes.BusinessEntities.Length > 0)

				{

					foreach (object businessEntity in faxes.BusinessEntities)

					{

						fax fax = (fax)businessEntity;
 

						faxList.Add(fax);

					}

				}

			}
 

			return faxList;

		}
 

		#endregion

	}

}

Open in new window

0
Comment
Question by:mattskelton
  • 4
  • 3
7 Comments
 
LVL 9

Expert Comment

by:Biffster007
ID: 21817320
Hi,

Is this working for all the other activity types??

MH
0
 
LVL 1

Author Comment

by:mattskelton
ID: 21818827
Hi,

I have only tried Facilities that have phonecall activities. I will try others & post back.

Matt
0
 
LVL 9

Expert Comment

by:Biffster007
ID: 21818837
Cheers,
MH
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 1

Author Comment

by:mattskelton
ID: 21824026
@ Biffster007,

Yes it is only Phonecalls. I couldn't test faxes but emails & letters work OK.

Thanks,

Matt
0
 
LVL 9

Accepted Solution

by:
Biffster007 earned 250 total points
ID: 21826399
Mroning,

Try retrieving all columns when you retrieve the phone call and try updating something else other than the 'from' field.  Something simply typed like a string field.

The phonecall is definitely active??

Also, what happens when you try and make the same change through the interface...success??

Cheers,
MH
0
 
LVL 1

Author Comment

by:mattskelton
ID: 21868867
Hi Biffster007,

Sorry for the long delay between posts. I am in the process of setting up a CRM test server so this callout has been pushed back until I get it up & running; I am thinking the end of next week. Thanks for your help so far.

Matt
0
 
LVL 9

Expert Comment

by:Biffster007
ID: 22217587
No worries...

Let me know how you get on.

MH
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
IOS Ipad app - generate customer quotes from iPad? 3 49
Definitions and default visual studio colors 5 58
VB.Net How to Exit Sub - Exit Form??? 5 48
SQL Exceptions 3 37
Automatically creating a Trello card using data from a Microsoft Dynamics CRM record turned out to be an easy project that yielded great results.  Here's how I did this for an internal team at General Code.
Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
In this video I am going to show you how to back up and restore Office 365 mailboxes using CodeTwo Backup for Office 365. Learn more about the tool used in this video here: http://www.codetwo.com/backup-for-office-365/ (http://www.codetwo.com/ba…
Internet Business Fax to Email Made Easy - With  eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, f…

911 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now