Archive
event.returnValue is not working after UR 12 – Fix
We use event.returnValue=false statement, to stop the event execution. (i.e., I can stop my crm form’s save action, if I write event.returnValue=false statement on my onsave() event).
After I upgraded to UR12, I was getting script error, if I use the event.returnValue statement.
Reason
- Update Rollup 12 and December 2012 Service Update support additional browsers by generating HTML that supports W3C standards.
- This requires removing dependencies on HTML components (HTC) that are specific to Internet Explorer.
- Hence event.returnValue statement has been deprecated
Fix
- Use context.getEventArgs().preventDefault() function to cancel the event execution
How do I use this
- First to get “context”, enable the OnSave event handler to pass the execution context as the first parameter to the OnSave event handler.
- Open customization form -> Form Properties and in “Handler Properties” window, select the “Pass execution ….” checkbox
-
- Next in your Jscript , read the context as first parameter
function onsave(context) {
// Prevent the event execution
context.getEventArgs().preventDefault();
}
Get more details on latest CRM JScript changes from this link
🙂
Retrieve records with Fetchxml using Jscript – CRM 2011
Retrieve the records using FetchXML is a convenient way as we can form the FetchXML easily using the ‘Advanced Find’ .
Once you have the FetchXML ready, below is the JScript to execute and read the result set.
- In this sample, I am fetching records from custom entity “Bikes” which has relationship with ‘Contact’ entity. (i.e., Fetch all the bikes of a Contact whose full name contains ‘Raj’)
- Note – I am using “xrmservicetoolkit” helper Jscript which is available in CodePlex. You just need to download the Jscript and refer to your CRM form.
function getBikesByContactName() {
var fetchXml =
“<fetch mapping=’logical’>” +
“<entity name=’raj_bike’>” +
“<attribute name=’raj_name’ />” +
“<attribute name=’createdon’ />” +
“<link-entity name=’contact’ from=’contactid’ to=’raj_customerid’ alias=’ad‘>” +
“<attribute name=’fullname’ />” +
“<filter type=’and’>” +
“<condition attribute=’fullname’ operator=’like’ value=’%raj%’ />” +
“</filter>” +
“</link-entity>” +
“</entity>” +
“</fetch>”;
// Execute the fetch
var bikes = XrmServiceToolkit.Soap.Fetch(fetchXml);
// Get the results by loop through ‘bikes’
for (var indxBikes = 0; indxBikes < bikes.length; indxBikes++) {
alert(“Bike Name – “+bikes[indxBikes].attributes.raj_name.value);
alert(“Created On – “+bikes[indxBikes].attributes.createdon.value);
// Get the related entity (i.e., Contact) attributes using LinkEntity alias)
alert(“Related entity attribute (Contact Name) – ” + bikes[indxBikes].attributes.ad.fullname.value);
}
}
🙂
Associate Campaign with related items using Jscript – CRM 2011
We can associate 2 entity records having N:N relationship using “AssociateRequest” SDK message. (How to associate)
But you get below error when you try to associate a Campaign record with Campaign related items such as Marketing List, Product, or Salesliterature using “AssociateRequest” SDK message.
Associate is not supported for CampaignItem Platform
To associate a Campaign, we have an exclusive SDK message “AddItemCampaignRequest”.
Below is the Jscript to associate Campaign with related records
function associateCampaignItem (campaignId, associateRecordId, associateRecordSchemaName) {
var requestMain = “”
requestMain += “<s:Envelope xmlns:s=\”http://schemas.xmlsoap.org/soap/envelope/\”>”;
requestMain += ” <s:Body>”;
requestMain += ” <Execute xmlns=\”http://schemas.microsoft.com/xrm/2011/Contracts/Services\” xmlns:i=\”http://www.w3.org/2001/XMLSchema-instance\”>”;
requestMain += ” <request i:type=\”b:AddItemCampaignRequest\” xmlns:a=\”http://schemas.microsoft.com/xrm/2011/Contracts\” xmlns:b=\”http://schemas.microsoft.com/crm/2011/Contracts\”>”;
requestMain += ” <a:Parameters xmlns:c=\”http://schemas.datacontract.org/2004/07/System.Collections.Generic\”>”;
requestMain += ” <a:KeyValuePairOfstringanyType>”;
requestMain += ” <c:key>CampaignId</c:key>”;
requestMain += ” <c:value i:type=\”d:guid\” xmlns:d=\”http://schemas.microsoft.com/2003/10/Serialization/\”>” + campaignId + “</c:value>”;
requestMain += ” </a:KeyValuePairOfstringanyType>”;
requestMain += ” <a:KeyValuePairOfstringanyType>”;
requestMain += ” <c:key>EntityId</c:key>”;
requestMain += ” <c:value i:type=\”d:guid\” xmlns:d=\”http://schemas.microsoft.com/2003/10/Serialization/\”>” + associateRecordId + “</c:value>”;
requestMain += ” </a:KeyValuePairOfstringanyType>”;
requestMain += ” <a:KeyValuePairOfstringanyType>”;
requestMain += ” <c:key>EntityName</c:key>”;
requestMain += ” <c:value i:type=\”d:string\” xmlns:d=\”http://www.w3.org/2001/XMLSchema\”>” + associateRecordSchemaName + “</c:value>”;
requestMain += ” </a:KeyValuePairOfstringanyType>”;
requestMain += ” </a:Parameters>”;
requestMain += ” <a:RequestId i:nil=\”true\” />”;
requestMain += ” <a:RequestName>AddItemCampaign</a:RequestName>”;
requestMain += ” </request>”;
requestMain += ” </Execute>”;
requestMain += ” </s:Body>”;
requestMain += “</s:Envelope>”;
var req = new XMLHttpRequest();
var OrgServicePath = “/XRMServices/2011/Organization.svc/web”;
var serverUrl = Xrm.Page.context.getServerUrl() + OrgServicePath;
req.open(“POST”, serverUrl, true)
// Responses will return XML. It isn’t possible to return JSON.
req.setRequestHeader(“Accept”, “application/xml, text/xml, */*”);
req.setRequestHeader(“Content-Type”, “text/xml; charset=utf-8”);
req.setRequestHeader(“SOAPAction”, “http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute”);
var successCallback = null;
var errorCallback = null;
req.onreadystatechange = function () { AddItemCampaignResponse(req); };
req.send(requestMain);
}
function AddItemCampaignResponse(req) {
if (req.readyState == 4) {
if (req.status == 200) {
alert(“Success”);
}
else {
alert(“Error – ” + req.responseXML);
}
}
}
How do I use
- Lets try to associate ‘Campaign’ with ‘Marketing List’ item using above script
- Pass the required arguments as specified below
var campaignId = “”; //Campaign GUID
var marketinglistId = “”; //Marketinglist GUID
var schemaName = “”; // Marketinglist entity Schema Name
associateCampaignItem(campaignId, marketinglistId, schemaName);
Below is the C# code to form the ‘AddItemCampaignRequest’
var request = new AddItemCampaignRequest { CampaignId = campaignId, EntityId = marketinglistId, EntityName = {Marketinglist entity Schema Name} };
🙂
Consuming WCF service from Jscript using JQuery
I recently got a requirement to host a WCF service in Azure and consume it client side using Jscript.
In this article, I am providing details on how to consume WCF service from Jscript with the help of JQuery.
In below example, service is a simple “Products.svc” contain 1 method “GetProducts()” and returns List<Product> (“Product” is custom class)
WCF Service
- Service Contract (IProductService.cs)
[ServiceContract(Namespace = “http://ABCproducts”,
Name = “IProductService”,
SessionMode = SessionMode.NotAllowed,
ProtectionLevel = ProtectionLevel.None)]
public interface IProductService{
[OperationContract]
[WebInvoke(
Method = “POST”,
BodyStyle = WebMessageBodyStyle.Wrapped,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
List<Product> GetProducts();
}
[DataContract]
public class Product{
string id = string.Empty;
string name = string.Empty;
[DataMember]
public string ProductId{
get { return id; }
set { id = value; }
}
[DataMember]
public string ProductName{
get { return name; }
set { name = value; }
}
}
- Service (ProductService.svc)
public List<Product> GetProducts(){
List<Product> products = new List<Product>();
Product P1 = new Product();
P1.Id = “1”;
P1.Name = “Mango”;
Product P2 = new Product();
P2.Id = “2”;
P2.Name = “Apple”;
products.Add(P1);
products.Add(P2);
return products;
}
- Service Binding (Web.config)
- Very important note is, the service endpoint has to be “webHttpBinding”; otherwise we get “Cannot process the message because the content type application\json was not the expected…” error.
- webHttpBinding is the REST-style binding, where you can hit a service URL and get back a result in either XML or JSON from the service.
- Add a “EndPointBehavior” with “webHttp” stack element.
- Below is the service configuration mentioned in my web.config file
<services>
<service name=”ProductService”>
<endpoint address=”” behaviorConfiguration=”endPtBehaviorJSon”
binding=”webHttpBinding” bindingConfiguration=”bindingWebHttp”
name=”wsBindingBFS” contract=”IProductService” />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name=”endPtBehaviorJSon“>
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
Jscript
- Since we are using JQuery, refer “JQuery.1.4.1.min.js” file
- In this example we are getting output in json format. (Observe “dataType property mentioned as “json”)
- “getProducts” is the function which communicate to service and gets “Product” collection as response in JSon format.
- The response comes in special format (i.e., WCF Service method name+Result) (i.e, GetProductsResult)
function getProducts() {
var serviceURL = “http://{Server Name}/ProductService.svc/GetProducts“;
$.ajax({
type: “POST”,
contentType: “application/json; charset=utf-8”,
url: serviceURL,
processData: false,
dataType: “json”,
//If the call succeeds
success:
function (response) {
retrieveProducts(response)
},
//If the call fails
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(“Error while retrieval – ” + XMLHttpRequest.responseText);
}
});
}
function retrieveProducts(response) {
// Result collection come as Response.{MethodName}+”Result”
if (response && response.GetProductsResult) {
$.each(response.GetProductsResult, function (i) {
alert(
“Product ID: ” + this.ProductId +
” Product Name: ” + this.ProductName);
});
}
}
Disabling controls in a section using JScript
We can’t disable a Section using “setDisabled(false)”, as Section is a container of controls.
Below is the logic to disable all the controls in a section
- Loop through all the page controls
- If the control’s parent is the specified section, disable the control
Below are the functions to disable controls in a Section. We need to pass “Section” object as parameter
function disableSectionFields(section) {
if (section) {
Xrm.Page.ui.controls.forEach(function (control, index) {
if (control && doesControlHaveAttribute(control)) {
if (control.getParent() === section) {
control.setDisabled(true);
}
}
});
}
}
// Validate if the control is not IFrame/webresource/subgrid as we can’t disable them
function doesControlHaveAttribute(control) {
var controlType = control.getControlType();
return controlType != “iframe” && controlType != “webresource” && controlType != “subgrid”;
}
// Get the Section object by Tab name & Section name
function getSection(tabName, sectionName) {
var tab = Xrm.Page.ui.tabs.get(tabName);
if (tab) {
return tab.sections.get(sectionName);
}
return null;
}
How do I call
- Assume my tab name is “tab_name” & section name is “section_name”
- Get the section object and pass to the “disableSectionFields” function as below
var mySection = getSection(“tab_name”, “section_name”);
if (mySection) {
disableSectionFields(mySection);
}
🙂
Set desired form as default using script – CRM 2011
I have an “Account” entity with multiple forms (i.e.,4 forms). My requirement is to set particular form as default form based on some logic.
Below is the script to set desired form as default.
function setMyFormAsDefault() {
// Set the form name you want to set as default
var myDefFormName = “ABC”;
// Get all available forms
if (Xrm.Page.ui.formSelector.items.get()) {
var forms = Xrm.Page.ui.formSelector.items.get();
var formId, formName;
for (var indxForms = 0; indxForms < forms.length; indxForms++) {
formId = forms[indxForms].getId();
formName = forms[indxForms].getLabel();
// Check form name and if it matches set current form as Default
if (formName == myDefFormName) {
forms[indxForms].navigate();
break;
}
}
}
}
- “Xrm.Page.ui.formSelector.items.get()” give us all available forms of the current entity
- getId() & getLabel() gives the form GUID and Form name
- “navigate()” loads the selected form
🙂
Read and Parse XML web resource using Jscript – CRM 2011
I have a XML file with below content added as a web resource (new_fruitsxml) in my CRM application
<?xml version=”1.0″ encoding=”utf-8″ ?>
<Fruits>
<Fruit Code=”App”>
<Name>Apple</Name>
<Price>20</Price>
</Fruit>
<Fruit Code=”Orng”>
<Name>Orange</Name>
<Price>10</Price>
</Fruit>
</Fruits>
Below is the Jscript code to read and parse the XML.
Note – The code uses JQuery to parse the XML, so you have to refer “jquery1.4.1.min.js” file to make the code works.
function ReadXML() {
try {
var xmlPath = “../WebResources/new_fruitsxml”;
$.ajax({
type: “GET”,
url: xmlPath,
dataType: “xml”,
success: parseXML
});
} catch (e) {
alert(“Error while reading XML; Description – ” + e.description);
}
}
function parseXML(xml) {
$(xml).find(“Fruit”).each(function () {
// Read attribute
alert(“Fruit Code – ” + $(this).attr(“Code”));
// Read Nodes
alert(“Fruit Name – ” + $(this).find(“Name”).text());
alert(“Fruit Price – ” + $(this).find(“Price”).text());
});
}
- In “ReadXML()” function we read the webresource and if the read succeeds, we mention the “parseXML()” function in “success: parseXML”
- So, on success, control comes to “parseXML()” function where we parse the XML
🙂
Disabling Assign ribbon button based on custom logic using jscript CRM 2011
In one of my requirement, I have to enable/disable “Assign” button on “Account” form based on one of my option set value (i.e.,accountcategorycode)
I followed below steps to achieve the requirement
- Get the Account “Assign” ribbon button details from “sdk\resources\exportedribbonxml\ accountribbon.xml” file from the SDK
- Open a note pad and copy below two nodes for reference
- Copy <Button Id=”Mscrm.Form.account.Assign”> tag
- Copy <CommandDefinition Id=”Mscrm.AssignPrimaryRecord”> tag
- Create a new jscript webresoure “new_Account_Ribbon” with function “enableAssignButton” and publish
- If the function returns true the “Assign” button gets enabled else disabled
- Define your own custom logic (Refer my custom logic below)
function enableAssignButton() {
try {
var fldCategory = Xrm.Page.data.entity.attributes.get(“accountcategorycode”);
if (fldCategory && fldCategory.getValue()) {
if (fldCategory.getValue() == 100000007) {
return true;
}
}
return false;
} catch (e) {
alert(“Error while enabling Assign button: ” + e.description);
}
}
- Create a new solution and include “Account” entity and export as Unmanaged solution
- Extract the zip folder and open “customizations.xml” using visual studio
- Navigate to <RibbonDiffXml> node
- Replace with below node (Refer comments to understand)
<RibbonDiffXml>
<CustomActions>
<!– Location will be ID of the Button–>
<CustomAction Location=”Mscrm.Form.account.Assign” Id=”Form.account.DisableAssign”>
<CommandUIDefinition>
<!– Paste the Assign button tag which you copied to notepad–>
<Button Id=”Mscrm.Form.account.Assign” ToolTipTitle=”$Resources:Ribbon.HomepageGrid.MainTab.Actions.Assign”
ToolTipDescription=”$Resources(EntityPluralDisplayName):Ribbon.Tooltip.Assign”
Command=”Mscrm.AssignPrimaryRecord” Sequence=”33″
LabelText=”$Resources:Ribbon.HomepageGrid.MainTab.Actions.Assign”
Alt=”$Resources:Ribbon.HomepageGrid.MainTab.Actions.Assign” Image16by16=”/_imgs/ribbon/Assign_16.png” Image32by32=”/_imgs/ribbon/Assign_32.png” TemplateAlias=”o1″ />
</CommandUIDefinition>
</CustomAction>
</CustomActions>
<Templates>
<RibbonTemplates Id=”Mscrm.Templates”></RibbonTemplates>
</Templates>
<CommandDefinitions>
<!– Paste the Assign button Command Definition which you copied to notepad –>
<CommandDefinition Id=”Mscrm.AssignPrimaryRecord”>
<EnableRules>
<EnableRule Id=”Mscrm.FormStateNotNew” />
<EnableRule Id=”Mscrm.AssignPrimaryPermission” />
<EnableRule Id=”Mscrm.NotOffline” />
<!– Add new Enable Rule–>
<EnableRule Id=”Form.account.AssignButton.EnableRule”/>
</EnableRules>
<DisplayRules>
<DisplayRule Id=”Mscrm.AssignPrimaryPermission” />
<DisplayRule Id=”Mscrm.NotClosedActivity” />
</DisplayRules>
<Actions>
<JavaScriptFunction FunctionName=”assignObject” Library=”/_static/_forms/form.js”>
<CrmParameter Value=”PrimaryEntityTypeCode” />
</JavaScriptFunction>
</Actions>
</CommandDefinition>
</CommandDefinitions>
<RuleDefinitions>
<TabDisplayRules />
<DisplayRules />
<EnableRules>
<!– Define Enable Rule–>
<EnableRule Id=”Form.account.AssignButton.EnableRule”>
<CustomRule Library=”$webresource:new_Account_Ribbon” FunctionName=”enableAssignButton“>
</CustomRule>
</EnableRule>
</EnableRules>
</RuleDefinitions>
<LocLabels />
</RibbonDiffXml>
🙂
Fixing time zone issues while reading datetime fields using jscript in CRM 2011
When you read datetime field values using OData or SOAP , you may not get exact datetime values if your CRM application is using by users from different time zones.
We can fix the problem by using the “timezonebias” field from current users “UserSettings“
timezonebias & timezonedaylightbias are system-calculated fields based on the time zone of current user
Follow below steps to fix the problem
- Read the “timezonebias” &“timezonedaylightbias” field by querying “UserSettings“ by current user id
- Get your datetime field and substract the “timezonebias & timezonedaylightbias” fields to get exact value
Below is the script for the above steps
- Read Current UserSettings
function RetrieveUserSettings(callBackFunction) {
try {
var serverUrl = Xrm.Page.context.getServerUrl();
var oDataEndpointUrl = serverUrl + “/XRMServices/2011/OrganizationData.svc/”;
//get current user id from context
var UserID = Xrm.Page.context.getUserId();
var RetrieveUserSetting = new XMLHttpRequest();
RetrieveUserSetting.open(“GET”, oDataEndpointUrl + “/UserSettingsSet(guid'” + UserID + “‘)”, true);
RetrieveUserSetting.setRequestHeader(“Accept”, “application/json”);
RetrieveUserSetting.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);
RetrieveUserSetting.onreadystatechange = function () {
callBackFunction(this);
};
RetrieveUserSetting.send();
} catch (e) {
alert(“Error on RetrieveUserSettings method”);
}
}
- Call the above function to get “timezonebias & timezonedaylightbias” fields
RetrieveUserSettings(RetrieveUserSettingCallBack);
- Read the “timezonebias” & “timezonedaylightbias” field from Call Back function and substract it from your datatime field value
function RetrieveUserSettingCallBack(retrievedUserSetting) {
try {
if (retrievedUserSetting.readyState == 4) {
if (retrievedUserSetting.status == 200) {
var retrievedUser = this.parent.JSON.parse(retrievedUserSetting.responseText).d;
// Assume you got datetime field to below object
var dateValue;
var actMinutes = dateValue.getMinutes();
alert(“Skewed datetime – ” + dateValue);
if (userSettings.TimeZoneBias != null) {
dateValue.setMinutes(userSettings.TimeZoneBias * -1);
}if (userSettings.TimeZoneDaylightBias != null) {
dateValue.setMinutes(userSettings.TimeZoneDaylightBias * -1);
}
// Add the actual minutesdateValue.setMinutes(actMinutes);
alert(“Exact datetime – ” + dateValue);
}
}
} catch (e) {
alert(e.Description);
}
}
Here is the article on handling the time zone differences in Plug-ins
🙂
Activate or Deactivate record using jscript
Hi,
Below is the script to Activate or Deactivate record using jscript.
// ‘State’ – Activate 0; InActive 1
// ‘Status’ – Active 1; InActive 2
function ActivateOrDeactivate(entityName, entityId, status, state) {
var setStateRequest = ‘<s:Envelope xmlns:s=”http://schemas.xmlsoap.org/soap/envelope/“>’ +
‘<s:Body>’ +
‘<Execute xmlns=”http://schemas.microsoft.com/xrm/2011/Contracts/Services” xmlns:i=”http://www.w3.org/2001/XMLSchema-instance“>’ +
‘<request i:type=”a:UpdateRequest” xmlns:a=”http://schemas.microsoft.com/xrm/2011/Contracts“>’ +
‘<a:Parameters xmlns:b=”http://schemas.datacontract.org/2004/07/System.Collections.Generic“>’ +
‘<a:KeyValuePairOfstringanyType>’ +
‘<b:key>EntityMoniker</b:key>’ +
‘<b:value i:type=”a:EntityReference”>’ +
‘<a:Id>’ + entityId + ‘</a:Id>’ +
‘<a:LogicalName>’ + entityName + ‘</a:LogicalName>’ +
‘<a:Name i:nil=”true”></a:Name>’ +
‘</b:value>’ +
‘</a:KeyValuePairOfstringanyType>’ +
‘<a:KeyValuePairOfstringanyType>’ +
‘<b:key>State</b:key>’ +
‘<b:value i:type=”a:OptionSetValue”>’ +
‘<a:Value>’ + state + ‘</a:Value>’ +
‘</b:value>’ +
‘</a:KeyValuePairOfstringanyType>’ +
‘<a:KeyValuePairOfstringanyType>’ +
‘<b:key>Status</b:key>’ +
‘<b:value i:type=”a:OptionSetValue”>’ +
‘<a:Value>’ + status + ‘</a:Value>’ +
‘</b:value>’ +
‘</a:KeyValuePairOfstringanyType>’ +
‘</a:Parameters>’ +
‘<a:RequestId i:nil=”true”></a:RequestId>’ +
‘<a:RequestName>SetState</a:RequestName>’ +
‘</request>’ +
‘</Execute>’ +
‘</s:Body>’ +
‘</s:Envelope>’;
var req = new XMLHttpRequest();
var serverUrl = Xrm.Page.context.getServerUrl();
req.open(“POST”, serverUrl, false);
req.setRequestHeader(“Content-Type”, “text/xml; charset=utf-8”);
req.setRequestHeader(“SOAPAction”, “http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute“);
req.send(setEntityStateRequest);
if (req.status != 200) {
alert(“Error while set status – “+req.responseXML);
}
}
How Do I call this method :-
- Below is the sample to activate “Contact” record
var contactId={contact GUID};
ActivateOrDeactivate(“contact”, contactId, 0, 1);
🙂