I'm writing code that pulls from a db and populates the information as an activity, I'm successfully able to add fields from db to description and subject field, but I cant seem to get it to link to an account?
Here is what i have tried;
foreach (var phoneNumber in phoneNumbers)
{
var potentialMatches = _xrm.AccountSet.Where(account => account.Address1_Telephone2.Equals(phoneNumbers)).ToList();
if (potentialMatches.Count > 0)
{
var accountMatch = potentialMatches.First();
var actualCRMAccount = (Account) _xrm.Retrieve("Account", accountMatch.Id, new Microsoft.Xrm.Sdk.Query.ColumnSet(true));
if (actualCRMAccount != null)
{
//Is this correct way?
new ActivityParty()
{
PartyId = new EntityReference(Account.EntityLogicalName, actualCRMAccount.Id)
};
activityParties.Add(new ActivityParty() {Id = actualCRMAccount.Id});
}
}
}
//RegardingObjectId not working
//RegardingObjectId = new EntityReference(Account.EntityLogicalName, recordRow.Cells[0].Value.ToString);
newMsg.To = activityParties;
newMsg.Description = recordRow.Cells[0].Value.ToString();
newMsg.Subject = recordRow.Cells[2].Value.ToString();
_xrm.Create(newMsg);
EDIT 1:
When i run it now im getting this warning
An unhandled exception of type 'System.ServiceModel.FaultException`1' occurred in Microsoft.Xrm.Sdk.dll .
Additional information: The entity with a name = 'Account' was not found in the MetadataCache.
This is the piece of code where it throws the warning
var actualCRMAccount = (Account)_xrm.Retrieve("Account", accountMatch.Id, new Microsoft.Xrm.Sdk.Query.ColumnSet(true));
Why would this be?
Edit 2:
I replaced Account with account, see below.
var actualCRMAccount = (Account)_xrm.Retrieve("account", accountMatch.Id, new Microsoft.Xrm.Sdk.Query.ColumnSet(true));
Edit 3:
Im now trying to do it for leads. but when i add this bit of code.
newMsg.RegardingObjectId = activityParties;
I get this error.
Cannot implicitly convert type 'System.Collections.Generic.List' to 'Microsoft.Xrm.Client.CrmEntityReference'
How can assign a value to RegardingObjectId.
Thanks for everyone's help.
The problem is that you´re adding the account via:
new ActivityParty() { Id = actualCRMAccount.Id }
To define a new ActivityParty you must set the PartyId property which is an entity reference for the chosen Type.
new ActivityParty() { PartyId = new EntityReference(Account.EntityLogicalName,actualCRMAccount.Id) }
should work.
There is a typo in the following line:
var potentialMatches = _xrm.AccountSet.Where(account => account.Address1_Telephone2.Equals(phoneNumbers)).ToList();
.Equals(phoneNumbers) should be: .Equals(phoneNumber)
Then replace the code after the retrieval of the account record with this:
var actualCRMAccount = (Account)_xrm.Retrieve("Account", accountMatch.Id, new Microsoft.Xrm.Sdk.Query.ColumnSet(true));
if (actualCRMAccount != null)
{
activityParties.Add(new ActivityParty { PartyId = actualCRMAccount.ToEntityReference() });
}
Related
I have a code that creates or updates an account. This block of code calls another method that saves the accountid on the contact record once it is chosen as the primary contact of the account.
However, when I try to run this, I am receiving this error:
An exception of type 'System.ServiceModel.FaultException`1' occurred in Microsoft.Xrm.Sdk.dll but was not handled in user code
Additional information: System.InvalidCastException: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #06B9DDED
It happends around the Update I do on the UpdateAccountNameContactEntity method. I've read a couple of sites, saying it might be the Guid I'm using, but I'm very new to this and I don't know how should I fix it.
I'm using ASP.NET MVC and Dynamics 365 right now. I have used this as my guide to create this.
Here is the code.
public void SaveAccount(AccountEntityModels objAccountModel)
{
using (OrganizationService service = new OrganizationService("CRM"))
{
Entity AccountEntity = new Entity("account");
if (objAccountModel.AccountID != Guid.Empty)
{
AccountEntity["accountid"] = objAccountModel.AccountID;
}
AccountEntity["name"] = objAccountModel.AccountName;
AccountEntity["telephone1"] = objAccountModel.Phone;
AccountEntity["fax"] = objAccountModel.Fax;
AccountEntity["websiteurl"] = objAccountModel.Website;
AccountEntity["primarycontactid"] = new Microsoft.Xrm.Sdk.EntityReference { Id = objAccountModel.PrimaryContact.Id, LogicalName = "account" };
if (objAccountModel.AccountID == Guid.Empty)
{
objAccountModel.AccountID = service.Create(AccountEntity);
UpdateAccountNameContactEntity(objAccountModel.AccountID, objAccountModel.PrimaryContact.Id);
}
else
{
service.Update(AccountEntity);
UpdateAccountNameContactEntity(objAccountModel.AccountID, objAccountModel.PrimaryContact.Id);
}
}
}
public void UpdateAccountNameContactEntity(Guid accountId, Guid contactId)
{
using (OrganizationService service = new OrganizationService("CRM"))
{
try
{
Entity contactEntity = new Entity("contact");
contactEntity["contactid"] = contactId;
contactEntity["parentcustomerid"] = accountId;
service.Update(contactEntity); //THIS IS WHERE I GET THE ERROR
}
catch (Exception ex)
{
}
}
}
You are trying to assign GUID in EntityReference.
Change this line
contactEntity["parentcustomerid"] = accountId;
like below:
contactEntity["parentcustomerid"] = new Microsoft.Xrm.Sdk.EntityReference { Id = accountId, LogicalName = "account" };
I've created an Azure active directory user and added the user to app roles.
Now i am retrieving this user and attempting to add it to more app roles.
var activeDirectoryUser = client.Users.Where(u => u.UserPrincipalName == user.UserName).ExecuteSingleAsync().Result as User;
As a precaution i want to first check if the user is already in an app role before adding however the problem is that the ApproleAssignments field on the User object is always empty. Even thou the user has app role assignments and i get an error if i try and add the user to the same app role.
Creating new app role assignment.
var appRoleAssignment = new AppRoleAssignment
{
Id = appRole.Id,
ResourceId = Guid.Parse(servicePrincpal.ObjectId),
PrincipalType = "User",
PrincipalId = Guid.Parse(user.ObjectId)
};
if(IsUserInAppRole(user,appRoleAssignment))return;
user.AppRoleAssignments.Add(appRoleAssignment);
user.UpdateAsync().Wait();
Checking if user is in app role.
private bool IsUserInAppRole(User user, AppRoleAssignment appRoleAssignment)
{
var userInApprole = user.AppRoleAssignments.Where(ara => ara.ObjectId == appRoleAssignment.Id.ToString());
return userInApprole.Any();
}
I'm using the latest version of Microsoft.Azure.ActiveDirectory.GraphClient library
Sorry for the late response. The following code worked for me. Not sure if you need to use the IUserFetcher interface, but your LINQ query fails because you are comparing the objectID of the assignment, with the appRole Id. What you need to compare is the ID of the assignment.
var userFetcher = user as IUserFetcher;
IPagedCollection<IAppRoleAssignment> rawObjects = userFetcher.AppRoleAssignments.ExecuteAsync().Result;
IList<IAppRoleAssignment> assignments = rawObjects.CurrentPage.ToList();
IAppRoleAssignment a = null;
a = assignments.Where(ara => ara.Id.Equals(appRole.Id)).First();
if (a != null) {
Console.WriteLine("Found assignment {0} for user {1}", appRole.Id, user.DisplayName);
}
Hope this helps...
var userFetcher = user as IUserFetcher;
IPagedCollection rawObjects = userFetcher.AppRoleAssignments.ExecuteAsync().Result;
IList<IAppRoleAssignment> assignments = rawObjects.CurrentPage.ToList();
Above lines of code is causing exception due to casting not done, if cast it as:
IPagedCollection rawObjects =
(IPagedCollection)userFetcher.AppRoleAssignments.ExecuteAsync().Result;
IList<IAppRoleAssignment> assignments =
(IList<IAppRoleAssignment>)rawObjects.CurrentPage.ToList();
Code get compiled successfully but gives runtime exception as:
Cannot implicitly convert type 'System.Collections.Generic.List' to 'System.Collections.Generic.IList'. An explicit conversion exists (are you missing a cast?)
Could you please guide how to use those two statements?
Update:
private static bool IsUserInRole(User user, AppRole appRole, bool roleAlreadyAssigned = false)
{
var userFetcher = user as IUserFetcher;
IPagedCollection rawObjects = (IPagedCollection)userFetcher.AppRoleAssignments.ExecuteAsync().Result;
foreach (IAppRoleAssignment item in rawObjects.CurrentPage)
{
if (item.Id == appRole.Id)
{
roleAlreadyAssigned = true; break;
}
}
return roleAlreadyAssigned;
}
The above code worked for me. Try this, hope this will help :)
As a requirement I cannot use the early bound context created with "CrmSvcUtil". The problem is that a new phonecall activity expects two fields ('from' and 'to') which are Entities of type activityparty. The standard XRM/CRM namespace does not contain a class similar to ActivityParty created with the Utility.
I tried filling it with an EntityCollection but then the field will be empty. Next I tried to recreate the structure of a working phonecall activity. EntityCollection "activityparty" -> with one Entity "activityparty" -> with EntityReference attribute "partyid" -> the entity ref (e.g. "contact" and the contact's id). But it simply does not work.
How can I create an ActivityParty (or better a phonecall Activity) with the "normal" Entitiy classes?
If I'm right you don't need to use an EntityCollection but an array of Entity
To create a phone call with late bound syntax will be:
Entity from1 = new Entity("activityparty");
Entity to1 = new Entity("activityparty");
Entity to2 = new Entity("activityparty"); // two contacts inside the to field
from1["partyid"]= new EntityReference("systemuser", userId);
to1["partyid"]= new EntityReference("contact", contact1Id);
to2["partyid"]= new EntityReference("contact", contact2Id);
Entity phonecall = new Entity("phonecall");
phonecall["from"] = new Entity[] { from1 };
phonecall["to"] = new Entity[] { to1, to2 };
// other phonecall fields
Guid phonecallId = service.Create(phonecall);
Even though I upvoted the answer but I had simmilar problem with serialization of ActivityParty. I came to solution that doesn't require you to give up on early bound entities.
what you need to do is something like this:
IEnumerable<ActivityParty> party = new [] { new ActivityParty { PartyId="", EntityLogicalName="..." } };
phonecall["to"] = new EntityCollection(party.Select(x => x.ToEntity<Entity>).ToList());
(I didn't test the code and wrote it from the air but you should feel the idea)
I vote for TrN because i was looking for any kind of example, and it's the only early bound example that i could find.
His example Actually helped me create an PhoneCall entity that had the Attribute "From" pointing to the Lead that actually made the call. I never fully understood the IEnumerable<ActivityParty> enumerator. Thanks to TrN i understand it enough to use it.
Here is my code regarding the PhoneCall activity that I've tested and it works. Everytime an existing Lead calls. The PhoneCall activity gets saved with the correct Attribute values linked to the correct Lead.
IEnumerable<ActivityParty> party = new[] { new ActivityParty { LogicalName = ActivityParty.EntityLogicalName , PartyId = eref2 } };
Console.WriteLine("Logging activity to {0}", firstName);
Console.WriteLine("... \n" );
PhoneCall newCall = new PhoneCall { Description = "Missed phone call from this lead", DirectionCode = true, RegardingObjectId = eref2,
Subject = "Missed Call", PhoneNumber = MissedCall, OwnerId = User, From = party };
Guid newCallId = service.Create(newCall);
Console.WriteLine("Log successfully created \n \n ");
As i said, For Kirschi this isnt the real solution given his requirement of not having any context. But anyone who wants/can use provided context and is curious how the IEnumerable<ActivityParty> works, this might help them to create a proper PhoneCall Activity.
Here is working code for the same. Feel free to reach out if anyone faces any issue.
private static void fetchRelatedPhoneCalls(IPluginExecutionContext context, IOrganizationService service, Guid yourGuid, Entity opp)
{
string strFetchPhoneCalls = string.Format(FetchQuery.bringFetchQueryForPhoneCalls(),yourGuid);
EntityCollection entPhoneCalls = (EntityCollection)service.RetrieveMultiple(new FetchExpression(strFetchPhoneCalls));
if (entPhoneCalls != null && entPhoneCalls.Entities.Count > 0)
{
for (int i = 0; i < entPhoneCalls.Entities.Count; i++)
{
Entity entPhoneCall = (Entity)entPhoneCalls.Entities[i];
string[] strAttributesPCtoRemove = new string[] { "createdon", "createdbyname", "createdby"
,"modifiedon", "modifiedby" ,"regardingobjectid","owninguser"
,"activityid", "instancetypecode", "activitytypecode" // PhoneCall Skip
};
Entity entNewPhoneCall = this.CloneRecordForEntity("phonecall", entPhoneCall, strAttributesPCtoRemove);
entNewPhoneCall["regardingobjectid"] = new EntityReference(context.PrimaryEntityName, context.PrimaryEntityId);
entNewPhoneCall["to"] = this.getActivityObject(entNewPhoneCall, "to");
entNewPhoneCall["from"] = this.getActivityObject(entNewPhoneCall, "from");
service.Create(entNewPhoneCall);
}
}
}
private static Entity CloneRecordForEntity(string targetEntityName, Entity sourceEntity, string[] strAttributestoRemove)
{
Entity clonedEntity = new Entity(targetEntityName);
AttributeCollection attributeKeys = sourceEntity.Attributes;
foreach (string key in attributeKeys.Keys)
{
if (Array.IndexOf(strAttributestoRemove, key) == -1)
{
if (!clonedEntity.Contains(key))
{
clonedEntity[key] = sourceEntity[key];
}
}
}
return clonedEntity;
}
private static EntityCollection getActivityObject(Entity entNewActivity, string activityFieldName)
{
Entity partyToFrom = new Entity("activityparty");
partyToFrom["partyid"] = ((EntityReference)((EntityCollection)entNewActivity[activityFieldName]).Entities[0].Attributes["partyid"]);
EntityCollection toFrom = new EntityCollection();
toFrom.Entities.Add(partyToFrom);
return toFrom;
}
I use Silverlight o-data services to interact with crm 2011 from my application
When I try to save the data in the entity SalesOrder as follows:
Private void beginSave()
{
SalesOrder orderHeader = new SalesOrder();
orderHeader.TransactionCurrencyId = new EntityReference(){ Id = new Guid("77D695B5-ACB4-E111-97BC-00155D55B216"), LogicalName="transactioncurrency" };
orderHeader.AccountId = new EntityReference() { Id = new Guid(MyClassGeneralOrder.customerId), LogicalName = "account" };
orderHeader.Name = "My Name";
Money totalAmount = new Money(); Money totalAmountBase = new Money();
Money totalTaxe = new Money(); Money totalAmountLessFreight = new Money();
totalAmount.Value = (decimal)MyClassGeneralOrder.InvoiceTotal;
totalAmountBase.Value = (decimal)MyClassGeneralOrder.totalRetail;
totalTaxe.Value = (decimal)MyClassGeneralOrder.totalCharges;
totalAmountLessFreight.Value = (decimal)MyClassGeneralOrder.totalNet;
orderHeader.TotalAmount = totalAmount;
orderHeader.TotalAmount_Base = totalAmountBase;
orderHeader.TotalTax = totalTaxe;
orderHeader.TotalAmountLessFreight = totalAmountLessFreight;
orderHeader.Description = element.Name;
orderHeader.PriceLevelId = new EntityReference() { Id = new Guid("03C5C4CB-EBD0-E111-8140-00155D55B216"), LogicalName="pricelevel" };
_context.AddToSalesOrderSet(orderHeader);
_context.BeginSaveChanges(SaveCallback, orderHeader);
}
private void SaveCallback(IAsyncResult result)
{
_context.EndSaveChanges(result);
}
In my function EndSaveChanges (result), I receive this error message : : « The Currency Cannot Be null ».
I don't understand why, because my "orderHeader.TransactionCurrencyId" field is not null.
I assuming that all of your other Currency fields are populated?
Any chance you have another plugin that is firing as a result of yours that is throwing the exception. That always seems to bite me. Try disabling all other plugins except for the one you're working on...
If you're still having issues, turn on crm server side tracing. You'll get much better error information. Use the CRM diagnostic tool to turn on trace logging: http://crmdiagtool2011.codeplex.com
Mostly your Guid is wrong and it's resulting in null. Make sure it's the correct GUID you are using or not. Run an advanced find against the entity and find the correct GUID. It's not a good idea to hard code the GUID. If you deploy your solutions to some other org it won't work.
It is necessary that after the creation of records in the table "Clients" took up ID. Later ID used to create a new entry in the "Clients_details".
var user = GetUsers();
var userdet = GetclientsDetails();
string hashedpass = getMd5Hash(UIPassword.Text);
var newreg = new Clients
{
login = UILogin.Text,
password = hashedpass,
subscribeid = Convert.ToInt32(UIId.Text)
};
user.InsertOnSubmit(newreg);
user.Context.SubmitChanges();
var details = new Clients_details
{
city = UICity.Text,
first_name = UIFirst_name.Text,
last_name = UIFamiliya.Text,
name = UIName.Text,
Clients = newreg
};
userdet.InsertOnSubmit(details);
userdet.Context.SubmitChanges();
After this code fails:
"An attempt was made to perform an operation Attach or Add in relation to an object that is not new, and possibly loaded from another DataContext. This operation is not supported."
How to properly create a record that does not appear a mistake? Thank you!
private static Table<Clients> GetUsers()
{
var dce = new BaseDBMLDataContext();
return dce.Clients;
}
private static Table<Clients_details> GetclientsDetails()
{
var dce = new BaseDBMLDataContext();
return dce.Clients_details;
}
Looks like userdet.Context and user.Context was built using a different dataContext and that needs to be created using the same dataContext rather than instantiating a new one.
I think you need to only call the SubmitChanges only once in the end, and also you need to make sure the user and userdet you are using share the same context
As the error clearly states, you're using different contexts (user and userdet) for each entity to add. You should have one DataContext and use that one to add the entities.
Yes looks like you're using two different instances of the same context:
user.Context.SubmitChanges();
userdet.Context.SubmitChanges();
A good approach to build up your entities should be something like :
//Create your client details entity
var details = new Clients_details
{
city = UICity.Text,
first_name = UIFirst_name.Text,
last_name = UIFamiliya.Text,
name = UIName.Text
};
//Create your client entity
var newreg = new Clients
{
login = UILogin.Text,
password = hashedpass,
subscribeid = Convert.ToInt32(UIId.Text),
//Assigning the details entity (FK) to the client
ClientDetails = details
};
//Saving both the client and its details
user.InsertOnSubmit(newreg);
user.Context.SubmitChanges();