Tuesday, September 13, 2011

How to interact with CRM form fields from within the Silverlight page

At times you may have a need to interact with the CRM form to read/update back the latest information after the processing completes from a custom application.

Say we add a button on the Entity form and when user will click on this button then we can read as well as set the value of the entity form fields. Below we have given the example to read the activityparty.

When you click on the button then it will open a child window. To access the CRM form we will need to use the Parent window from which this child window was called. Here we are reading the values of the Sender attribute of the Email.

dynamic win = HtmlPage.Window;
dynamic opener = win.parent.opener;
ScriptObject xrm = (ScriptObject)opener.GetProperty("Xrm");
ScriptObject page = (ScriptObject)xrm.GetProperty("Page");
dynamic dynamicPage = page;

dynamic lookupItems = dynamicPage.data.entity.attributes.get("to").getValue();
HtmlPage.Window.Invoke("readLookup", lookupItems);

“To” attribute is of the type lookup and it will be an array of objects. To read the values for this lookup you need to write the following script on the html page.

function readLookup(source) {

if (source == null) {
return;
}

var array = new Array();
array = source;
for (i = 0; i < array.length; i++) {
alert(array[i].entityType);
alert(array[i].id);
alert(array[i].name);
}

}

Now say you want to update the Subject of the Email from within the Silverlight custom application, you can refer the CRM form and update the controls on the form as shown below

dynamicPage.data.entity.attributes.get("subject").setValue("Test 1234");

Since Subject is a text field it could be done as simply as above.

But to set the value for the lookup and date type of attributes, there is still more to be done. For this we need to add a java script web resource on the required entity. This web resource will contain the function to set the lookup and the date value. We then need to call this function from the Silverlight page. Code below explains how this can be done

dynamic parent = win.parent.opener;
parent.setLookupValue();
he SetLookupValue will contain the code to set the value for the lookup. As given below.

Xrm.Page.data.entity.attributes.get("regardingobjectid").setValue(array);


Hope this helps in designing richer Silverlight applications that interact better with the CRM forms.

Tuesday, September 6, 2011

Retrieve related entity records along wih the Primary entity using Retrieve Method

We have always known the Retrieve request to be able to retrieve the data of the requested entity based on the id provided. However in CRM 2011, the Retrieve request can read not only the properties of the primary entity but also the referenced entity like in a 1-N or N-N or N-1 relationship. Given that it supports all the three types of relationships it could be an advantage over the LinkEntity feature.

For example, if we want to retrieve the active contacts related to an account then, we can design the query as shown in the below code,

using (OrganizationServiceProxy _orgserviceproxy = new OrganizationServiceProxy(new Uri(OrganizationUri), null, Credentials, null))
{

//create the query expression object
QueryExpression query = new QueryExpression();

//Query on reated entity records
query.EntityName = "contact";

//Retrieve the all attributes of the related record
query.ColumnSet = new ColumnSet(true);

//create the relationship object
Relationship relationship = new Relationship();

//add the condition where you can retrieve only the account related active contacts
query.Criteria = new FilterExpression();
query.Criteria.AddCondition(new ConditionExpression("statecode", ConditionOperator.Equal, "Active"));

// name of relationship between account & contact
relationship.SchemaName = "contact_customer_accounts";

//create relationshipQueryCollection Object
RelationshipQueryCollection relatedEntity = new RelationshipQueryCollection();

//Add the your relation and query to the RelationshipQueryCollection
relatedEntity.Add(relationship, query);

//create the retrieve request object
RetrieveRequest request = new RetrieveRequest();

//add the relatedentities query
request.RelatedEntitiesQuery = relatedEntity;

//set column to and the condition for the account
request.ColumnSet = new ColumnSet("accountid");
request.Target = new EntityReference { Id = accountID, LogicalName = "account" };

//execute the request
RetrieveResponse response = (RetrieveResponse)_orgserviceproxy.Execute(request);

// here you can check collection count
if (((DataCollection)(((RelatedEntityCollection)(response.Entity.RelatedEntities)))).Contains(new Relationship("contact_customer_accounts")) &&((DataCollection)(((RelatedEntityCollection)(response.Entity.RelatedEntities))))[new Relationship("contact_customer_accounts")].Entities.Count > 0)
return true;
else
return false;
}

One limitation though, is that it is only available with the Retrieve Request and not the Retrieve Multiple request. Wonder why this has not be added for Retrieve Multiple request as this can be of great help to return all the data required in one request.

Sunday, August 28, 2011

Add a button to create a new related record

To create a new record for a related entity we need to move to that related entity view in the Main form and then use the add button there to actually open a new form for the related entity. At times this is considered time consuming and it would be good to have a button on the main form from where we can add a new related record directly.

While it is easy to add a button to call a new form, we just need to pass in the URL of the new form which is similar to the below

“http://mycrm/myOrg/main.aspx?etn=account&pagetype=entityrecord”

But what differentiates a new record from a new related record is that in related record, the common fields and mappings from the parent record are auto-filled when the new form is opened. The above URL will not copy the mapping fields from the parent record.

To open a new related record form you need to use the following url


var url = Xrm.Page.context.getServerUrl()+"main.aspx?etn= “+Child entity schema name+” &extraqs=%3f_CreateFromId%3d"+ parentRecordId +"%26_CreateFromType%3d”+Parent Entity type code +”%26etn%“+Child entity schema name+” &pagetype=entityrecord";

Hopefully this little trick would let you minimize a few clicks!

Wednesday, August 17, 2011

CRM 2011 messages using SOAP

Microsoft has provided CRM ODATA service to perform actions on CRM data. However, the ODATA service only allows you to perform basic CRUD operations on CRM entities. If you want to perform other operations like Change state or perhaps read Metadata information, you will need to access the CRM SOAP service.

You can add the reference to CRM SOAP service using the following URL.
http://Server_name/Organization_name/XRMServices/2011/Organization.svc

We have encountered various issues while trying to get our messages executed through SOAP. Here we are going to list out all the messages and the properties that are required to be set to get the SOAP message to execute successfully.

RetrieveAttribute request – This request allows you to read the metadata information of a given attribute.

TestApplication.CrmSdk.OrganizationRequest request = new TestApplication.CrmSdk.OrganizationRequest() { RequestName = "RetrieveAttribute" };

//Set all required parameters of request
request["EntityLogicalName"] = "Account";
request["RetrieveAsIfPublished"] = true;
request["LogicalName"] = "Address1_AddressTypeCode ";
request["MetadataId"] = Guid.Empty;

//Execute the request
service.Execute(request);

In call back function call end execute function to execute request and get response of request as shown in below line of code,

//end the request
TestApplication.CrmSdk.OrganizationResponse response = service.EndExecute(result);

//read the result
CrmSdk.PicklistAttributeMetadata picklist = (CrmSdk.PicklistAttributeMetadata)response["AttributeMetadata"];

In the above request make you to set the MetadataID to Guid.Empty or this message would not execute.


QualifyLead Request – This request allows you to qualify a lead and create Account, Contact and Opportunity from the lead record.

OrganizationRequest _qualifyRequest = new OrganizationRequest() { RequestName = "QualifyLead" };

//Initialize Member of qualify request as shown in below code

//set Account
_qualifyRequest["CreateAccount"] = true;

//set contact
_qualifyRequest["CreateContact"] = true;

//set opportunity
_qualifyRequest["CreateOpportunity"] = true;

//set Status
OptionSetValue status = new OptionSetValue();
status.Value = -1;
_qualifyRequest["Status"] = status;

//set currency
EntityReference currency = new EntityReference();
currency.LogicalName = "transactioncurrency";
currency.Id = new Guid(transactioncurrencyId);
_qualifyRequest["OpportunityCurrencyId"] = currency;


//set customer
EntityReference customer = new EntityReference();
customer .LogicalName = "account";
currency.Id = new Guid(accountId);
_qualifyRequest["OpportunityCustomerId "] = customer;

//set SourceCampaign
_qualifyRequest["SourceCampaignId"] = null;

//Execute the request
_service.BeginExecute(_qualifyRequest, new AsyncCallback(QualifyLeadCallBack), _service);


In call back function call end execute function to execute request and get response of request as shown in below line of code,

OrganizationResponse response = orgService.EndExecute(result);

When request execute successfully it return entityreferencecollection.We get create record using below line of code it return entityreferencecollection

EntityReferenceCollection entityCollection = (EntityReferenceCollection)response

SetState Request – Using this request we can activate/de-activate the record.

To activate/de-activate the record in Silverlight.

To activate/de-activate the record in Silverlight you have to trap “SetStateRequest”.

The member of “SetStateRequest” is given below,you have set this member.
EntityMoniker
State
Status

To trap “SetStateRequest” in Silverlight you have create object of “OrganizationRequest” and set RequestName =”SetState” , as shown in below line of code

SoapServiceReference.OrganizationRequest request = new SoapServiceReference.OrganizationRequest() { RequestName = "SetState" };

After that you have set member of SetStateRequest ,as shown in below lines of code

1. EntityMoniker
-It is of Entity reference type.In EntityMoniker you have set “Id” and “LogicalName” of record as shown in below line of code

SoapServiceReference.EntityReference ServiceActivity = new SoapServiceReference.EntityReference() { Id =accountId, LogicalName = "account" };

2. State - It is of optionset type. In state you have set value as “0” for Active or “1” for InActive. as shown in below line of code
SoapServiceReference.OptionSetValue States = new SoapServiceReference.OptionSetValue();
States.Value = 0; or States.Value = 1;

3. Status - It is of optionset type. In status you have set set value as “1” for Active or “2” for InActive. as shown in below line of code
SoapServiceReference.OptionSetValue Status = new SoapServiceReference.OptionSetValue();
Status.Value = 1; or Status.Value = 2;

Above code collectively return as below.
SoapServiceReference.OrganizationRequest request = new SoapServiceReference.OrganizationRequest() { RequestName = "SetState" };

request["EntityMoniker"] = ServiceActivity;
request["State"] = States;
request["Status"] = Status;

After setting all member execute the request as shown in below line of code.
Sevcie. BeginExecute method -Pass three parameter “Request”,”Async method”,and “Soap Service” as shown below line of code
//Excute request
service.BeginExecute(request, new AsyncCallback(SetActivityStateCompleted), service);
In callback fuction call below line of code,to execute the request.
SoapServiceReference.OrganizationResponse response = service.EndExecute(result);
If request execute successfully.It activate/de-activate the record.

Monday, August 8, 2011

Notify the dialog to end

When you design a Dialog, make sure you explicitly stop the dialog when all the steps of the dialog have completed using the “Stop Dialog” step



Failure to do so might result in you receiving the following error when all steps have been processed.



The above error is pretty misleading and we spent hours trying to identify which data is missing before we finally managed to get this to work after adding the “Stop Dialog” step.