Tuesday, January 10, 2012

Tip - Hide fields on CRM form without messing up the form layout

Generally if you hide a field through script, CRM does not redesign the layout to use up the blank space left from the hiding of a field on the form. This makes it very obvious that there must have been some control that is now not visible to the user. To avoid this you can make use of the CRM 2011 ability to add the same field multiple times on a form.

Say for example you would like to hide the Estimate Revenue field from the form and make it available conditionally.



Simple script to hide the field would display the form as shown below.





To make sure that such empty spaces are not visible on the form, you can instead create 2 sections on the form, one with the Est. Revenue field and the other without the field.





Through script you can then show/hide the entire section. This way the form layout is not affected.


Friday, January 6, 2012

Read Form Id or Form XML of a specified entity form

CRM 2011 now allows multiple forms to be designed for an entity and based on the security roles display the appropriate form.

During the development we once came across the need to get the Formid for each of the forms created for an entity. We did not want to hard code the formid in the ribbon button as the id’s may change between test and production environments.

We can programmatically retrieve the FormId of an entity through Jscript.

The schema name for the entity that stores the information about the various forms is SystemForm. The code below retrieves the id for the specified form based on the form name.


function RetrieveGetFormIDRecord(formName)
{
var cols="";
try
{
var xml = "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>"+
" <soapenv:Body>"+
" <RetrieveMultiple xmlns='http://schemas.microsoft.com/xrm/2011/Contracts/Services' xmlns:i='http://www.w3.org/2001/XMLSchema-instance'>"+
" <query i:type='a:QueryExpression' xmlns:a='http://schemas.microsoft.com/xrm/2011/Contracts'>"+
" <a:ColumnSet>"+
" <a:AllColumns>false</a:AllColumns>"+
" <a:Columns xmlns:b='http://schemas.microsoft.com/2003/10/Serialization/Arrays'>"+
" <b:string>formid</b:string>"+
" </a:Columns>"+
" </a:ColumnSet>"+
" <a:Criteria>"+
" <a:Conditions>"+
" <a:ConditionExpression>"+
" <a:AttributeName>name</a:AttributeName>"+
" <a:Operator>Equal</a:Operator>"+
" <a:Values xmlns:b='http://schemas.microsoft.com/2003/10/Serialization/Arrays'>"+
" <b:anyType i:type='c:string' xmlns:c='http://www.w3.org/2001/XMLSchema'>"+formName+"</b:anyType>"+
" </a:Values>"+
" </a:ConditionExpression>"+
" </a:Conditions>"+
" <a:FilterOperator>And</a:FilterOperator>"+
" <a:Filters />"+
" </a:Criteria>"+
" <a:Distinct>false</a:Distinct>"+
" <a:EntityName>systemform</a:EntityName>"+
" <a:LinkEntities />"+
" <a:Orders />"+
" <a:PageInfo>"+
" <a:Count>0</a:Count>"+
" <a:PageNumber>0</a:PageNumber>"+
" <a:PagingCookie i:nil='true' />"+
" <a:ReturnTotalRecordCount>true</a:ReturnTotalRecordCount>"+
" </a:PageInfo>"+
" <a:NoLock>false</a:NoLock>"+
" </query>"+
" </RetrieveMultiple>"+
" </soapenv:Body>"+
"</soapenv:Envelope>";


// Prepare the xmlHttpObject and send the request.
var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
xHReq.Open("POST", Xrm.Page.context.getServerUrl() + "/XRMServices/2011/organization.svc/web", false);
xHReq.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/RetrieveMultiple");
xHReq.setRequestHeader("Content-type", "text/xml; charset=utf-8");
xHReq.setRequestHeader("Content-Length", xml.length);
xHReq.send(xml);

// Capture the result.
var resultXml = xHReq.responseXML;

var errorCount = resultXml.selectNodes('//error').length;
if (errorCount != 0)
{
var msg = resultXml.selectSingleNode('//description').nodeTypedValue;
alert(msg);
return;
}

// Parse and display the results.
var results = resultXml.getElementsByTagName('a:Entity');
//if only one zip code records found
if (results.length != 0 )
{
//alert("Lenght: "+results.length);
var attribs = results[0].getElementsByTagName('a:Attributes/a:KeyValuePairOfstringanyType');
if (attribs.length == 0)
{
alert("No data found in enitty.");
return;
}

if(attribs[0].selectSingleNode('./b:key').nodeTypedValue =="formid" )
{
//set the field values
var value= attribs[0].selectSingleNode('./b:value').nodeTypedValue;
alert("FormID:"+value);
}
}

}//end of try
catch(e)
{
alert("RetrieveGetFormIDRecordErr: "+e.description);
}
}//end of RetrieveGetFormIDRecord

</Snip>

In the above code, we just need to pass the form name and it will return the form id. In the above query we can add the condition to filter by an entity like account forms as well by setting the “objecttypecode”.

Once you have the formid you can open the form using the following url

var accountPage= Xrm.Page.context.getServerUrl()+ "/main.aspx?etn=account&extraqs=formid%3D"+value+"%0D%0A&pagetype=entityrecord";
window.open(accountPage);






Thursday, January 5, 2012

MVP Awarded!

2012 starts with a bang for Team Inogic. We take pride in announcing that one of our Team Members known to you all as Sam is now a Dynamics CRM MVP.

Well done!!!

Tuesday, December 27, 2011

Import data now allows you to Create the entities as well

CRM 4.0 made available the feature to import data into CRM using the Import feature. But this was only restricted to importing data in existing entities.


In CRM 2011 this feature has now been extended to go one step further and even create the entity in CRM to hold the data in case an entity for that does not already exist. CRM 2011 also provides us the capability to define the entity attributes as well while importing the data.

Let me explain the step one by one to give the exact understanding of the dynamic concept.

-Click on “Import Data” button


- A dialog to import your CSV data will be displayed as given in the below screen shot.

- After that Dialog to which we want to map the data will be displayed. In that window select the “Create New” as given in the below screen shot. Provide the name for the new entity along with the Primary Field name.
- After that a window to map the attributes to the data will be shown as given below. -For mapping of each column we can create new field as given in the below screen shot. Please make sure to provide mapping for primary field for Ex: in our case “Name”.
- After that a window showing the mapping summary will be displayed as given below.
- After that click on submit button

-After successfully importing the data, you will notice that the custom entity has also been created in CRM. You have to add the fields on the form as it is not implicitly added to the form


Tuesday, December 20, 2011

ODATA Properties and Methods Explored…

Here are some of the ODATA context properties that would help us during debugging and understanding the behavior of the context when performing various operations.
1. DataServiceContext.Entities:
Gets a list of all the records currently being tracked by the DataServiceContext. While using OData service, we frequently get the error that context already tracking the record. With the "Entities" property, we can check total records tracked by context. As well as after adding record to the set, we can check whether context.Entities count increases.

2. DataServiceContext.IgnoreMissingProperties:
Gets or sets whether the properties read from the type must be mapped to properties on the client-side type. Always set this property to true. This helps when say you have downloaded the ODATA reference and developed your application based on that and later there are additional attributes added to the entities. With this property set to True it will ignore the new properties that were added later on and not throw an error regarding missing properties.

3. DataServiceContext.Links:
Gets the collection of all associations or links currently being tracked by the DataServiceContext object which are added using AddRelatedObject, AddLink and SetLink methods.

4. DataServiceContext.AddLink(source, sourceProperty, target):
Adds the specified link to the set of objects the DataServiceContext is tracking. Before adding a link, both source and target must be tracked by context.
Example: context.AddLink(parentRecord, "relationshipName", childRecord);

5. DataServiceContext.SetLink(source, sourceProperty, target):
Notifies the DataServiceContext that a new link exists between the objects specified and that the link is represented by the property specified by the sourceProperty parameter. Before adding a link, both source and target must be tracked by context.
Example: context.AddLink(childRecord, "relationshipName", parentRecord);

6. DataServiceContext.AddRelatedObject(source, sourceProperty, target):
Adds a related object to the context and creates the link that defines the relationship between the two objects in a single request.
Example: context.AddLink(childRecord, "relationshipName", parentRecord);

Note: AddLink and SetLink are very useful methods as using these we can make a compound request (i.e. can add parent and child together). This will only work when your parentLink (a field that is lookup to parent) is not required on child record. When we tried to create an invoice with invoice details, it was giving an error and only invoice header gets created. This is because for Invoice detail, invoiceid is a required field and it cannot be created without and invoice id provided. However this does work in cases, where the child entity can be created independently and the parent entity is not a required attribute in the child entity.


-------------------------------------------------------
Posted by: Inogic
For more information/discussions (documents, sample code snippets, detailed work flow or diagrams),
Please be free to visit the following links or email us:
Web: http://www.inogic.com
Blog: http://inogic.blogspot.com
Email: news@inogic.com
-----------------------------------------------------