In this example , i will display the number of calls made to an account .Number of calls will display on an account as soon as Sales or marketing people complete the phone calls.
I will make a new read only field on account Form “Total number of calls(new_totalnumberofcalls)” as shown in below figure.
Figure “Call made to an account
Figure = Displaying Total number of calls
Plugin will be registered as ” SetStateDynamicEntity”.
Code :
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.Sdk.Query;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
namespace Microsoft.Crm.Sdk.UpdatingAccount
{
public class endless : IPlugin
{
// assigning default value for total number of calls
int NumberOfCalls= 1;
public void Execute(IPluginExecutionContext context)
{
if (context.PrimaryEntityName == EntityName.phonecall.ToString() && context.InputParameters.Properties.Contains(“EntityMoniker”) && context.InputParameters.Properties.Contains(“State”))
{
// I will get the current Phone call Id and its state
Guid PhoneCallId = ((Moniker)context.InputParameters.Properties["EntityMoniker"]).Id;
PhoneCallState stateCode = (PhoneCallState)Enum.Parse(typeof(PhoneCallState), ((string)context.InputParameters.Properties["State"]));
// Only update the regarding account ‘s field , if the phone call is “completed”
if (stateCode == PhoneCallState.Completed)
{
ICrmService service = context.CreateCrmService(false);
phonecall myphonecall = (phonecall)service.Retrieve(EntityName.phonecall.ToString(),
PhoneCallId, new AllColumns());
string regardingType = myphonecall.regardingobjectid.type;
Guid regardingId = myphonecall.regardingobjectid.Value;
// Invalid customer type. then return .
if (regardingType != EntityName.account.ToString())
{
return;
}
// Retrieve the Account’s traget field
TargetRetrieveAccount target = new TargetRetrieveAccount();
target.EntityId = regardingId;
RetrieveRequest getAccount = new RetrieveRequest(); getAccount.ReturnDynamicEntities = true;
getAccount.Target = target;
getAccount.ColumnSet = new AllColumns();
// Get the account
RetrieveResponse retrieved = (RetrieveResponse)service.Execute(getAccount);
DynamicEntity regardingAccount = (DynamicEntity)retrieved.BusinessEntity;
// If the “Total number of call” exists, update them ,otherwise set it
if (regardingAccount.Properties.Contains(“new_totalnumberofcalls”))
{
((CrmNumber)regardingAccount.Properties["new_totalnumberofcalls"]).Value += NumberOfCalls;
}
else
{
regardingAccount.Properties.Add(new CrmNumberProperty(“new_totalnumberofcalls”, new CrmNumber(NumberOfCalls))); }
// Updateing
service.Update(regardingAccount);
} }
}
}
}
Hi Amir,
Was just looking for this one. But how do i register this one though the registration tool?
Hej Bjørn,
Thats true .
Download the CRM SDK and search for plugin registeration tool .It will tell you how to register the plugin .It is quite simple .Just let me know if you could not find it.
i have created plugin like this and register it but still not getting total phone call value
Have you registered the plugin with message “SetStateDynamicEntity” on Phone entity?
Make it sure that this field exist on account “new_totalnumberofcalls”.
i got it,
thanks Aamir Its working fine now…………..
Why could you not just do this through a workflow?
Daniel
it was just an example to show plugin :=)
how to registered the plugin with message “SetStateDynamicEntity” on Phone entity?
Sun,
in Plugin registeration tool , enter SetStateDynamicEntity in “Message” and then choose Phone entity.
Thanks
Now Error has occur when i change status of phone call.
what would be problem?
Can you please check the event log to get the detailed error .
Hi Amir,
I need to create a Plugin for Order(SalesOrder) and Order Product(SalesOrder detail) entities. I have two custom field on Order Product:-
1 Product Type = picklist(options A, B)
2 Product Value = money.
An order can have many order products with specific type and values against them. What I want is when the user save/close the order product form, The two fields on the Order Form ( Parent) should be updated respectively.
The two fields on the Order form are
A Total
B Total.
How can I do that? Any code would be appreciated
Mehmood,
instead of plugin you can use the existing workflow and check if you can update (order) when the status of one entity changed (order product).
If it is possible then you do not need to write code.
Otherwise you can write plugin which fire when order product is closed(i think you shuld use entity moniker) .As it is not crm or plugin tool infornt of me otherwise i could tell you which message to use when you close order product to retrieve the information to update the another entity.
Well, I cannot use the existing fields because if in future microsoft made the changes in the default workflows my code might not work so I have to use the custom fields instead of default ones.
I would be obliged if you could let me know
1) how to access the custom fields in DynamicEntity object
2) how to get the id of parent (salesorder) entity and its custom fields & how to update them.
3) Which Message should I use to trigger the code.
Thanks in advance.
i make this code but the last line
service.Update(regardingAccount); giving error
while i registered plugin with message -setstatedynamic
primary entity -phonecall
and on post stage
please tell me i m right when i m registring it
Try to register the plugin on create or Update phone call and make a test if there is any issue?
hello aamir ,
no,its not working on create and update step when registered ….
while i am using same code.
Hello Manoj,
Instead of updating Account , try simply to create a task so you have an idea what is wrong :
task myTask = new task();
myTask.Subject =”hello World”;
service.create(myTask);
Check any error in event log which might point you to a class or specific method.
its working now ..thanks Aamir…
Dear all..
i’m trying to use this code, but in the execute it gives me error
RetrieveResponse retrieved = (RetrieveResponse)service.Execute(getAccount);
aslo tried to create task and on the create() method gave me same error.
Server was unable to process request.
Exception information:
Exception type: InvalidPluginExecutionException
Exception message: Server was unable to process request.
Web Service Plug-in failed in OrganizationId: c4b31b29-f85d-df11-a377-00155d8a4e04; SdkMessageProcessingStepId: a35543ae-2c17-e011-b47b-00155dc86809; EntityName: phonecall; Stage: 50; MessageName: SetStateDynamicEntity; AssemblyName: PluginToUpdate.Update, PluginToUpdate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=dfdabbae955fd31b; ClassName: PluginToUpdate.Update; Exception: Unhandled Exception: System.Web.Services.Protocols.SoapException: Server was unable to process request.
Detail:
0x80044150Generic SQL error.
Platform
at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
at Microsoft.Crm.SdkTypeProxy.CrmService.Create(BusinessEntity entity)
at PluginToUpdate.Update.Execute(IPluginExecutionContext context)
at Microsoft.Crm.Extensibility.PluginStep.Execute(PipelineExecutionContext context)
appreciate your fast responce
Hi,
You can do something like :
1.Check on CRM server if Asynchronous Processing Service is woring?
2. Have you signed the plugin with strong key?
3. Lets do very small example on a Plugin “Post Create” Message .
public class test :IPlugin
{
public void Execute(IPluginExecutionContext context)
{
ICrmService service = context.CreateCrmService(true);
task TestTask = new task();
TestTask.Subject =”Hello World”;
service.create(TestTask);
}
}
i got this
Invalid format of input XML for request Retrieve: required field ‘ColumnSet’ is missing.
fixed when set this from
ICrmService service = context.CreateCrmService(false);
to
ICrmService service = context.CreateCrmService(context.userid);
Hello Aamir,
i want some suggestion on my problem …i have two custom field product and unit …which is look up and has relationship with ‘product’ and ‘unit’ system entity. i want that when i will select product then unit have filtered unit data for that particular product
You can use Javascript to do it .
Use the GUID of product to search for Unit and then fill the lookup with unit id.
Search Google how to use webservices in JavaScript in Microsoft CRM.
/Aamir
hello Aamir,
sir , i have a problem in SN accelerator …i could not get replies by twitter in my ms crm …’get replies’ workflow not working while get update workflow runs perfectly. can u explain me some functionality about get replies by twitter in ms crm. means whose entity and workflow run when i want to get replies on my status on twitter
hello aamir!!
need suggestion ….
i want to print invoice with mail merge functionality .how could i implement this?
Hello aamir ,
i want to add activity in navigation pane of my entity form.i did not add it on the time of creation,Now i dont want to delete my entity for attach activity.Is there anyway to attach acvity on my entity form?
Thanks with Regards,
Manoj Chauhan
Cool. Nice post on the CRM plugin creation! Thanks for the details, including coding.
Hello aamir ,
i have a problem in ms crm 2011,can u suggest me for this ….when i am writing a custom workflow or plugin in vs 2010 for ms crm 2011..i am not able to get strong type classes.
for e.g- i want to make instance of account class as
Account acc =new Account();
i am not abel to get these classes with assembly Microsoft.Xrm.Sdk and Microsoft.Crm.Sdk.proxy. please suggest me out .
Thanks
Hi,
Search for this topic in CRM SDK. You need to create proxy class and then refer that class in your code.
“Use the Early Bound Entity Classes for Create, Update, and Delete”
try this :
Entity newAccount= new Entity(“account”);
newAccount["name"] = “Test Account”;
Thanks for the reply aamir,yes i tried that and its was working but for other work i need business data that can be implemented by that way so….for example i would like to upgrade this method in ms crm 2011.
private void SplitEmailIds(string AccountId, ICrmService CrmService, IWorkflowContext Context)
{
string[] arrId = AccountId.Split(‘~’);
sAccountGuid = arrId[0];
activityparty[] apTo = new activityparty[100];
for (int i = 0; i < arrId.Length – 1; i++)
{
activityparty apAccId = new activityparty();
apAccId.partyid = new Lookup();
apAccId.partyid.type = EntityName.account.ToString();
apAccId.partyid.Value = new Guid(arrId[i]);
apTo[i] = apAccId;
}
}
//Manoj chauhan