CRM On Save “Server is Busy” Error

Some time we need to write the code that on save we want to stop the default save event and trigger our own because we want to do some action as we click of the save button but if any plugin error comes we want to revert back that changes or we want to perform some other action.

For example: On click of start button I wan’t to disable some fields but if I get any plugin error and I click okay on that error my fields should again get activated. This is not achievable through the save button click as the default save button doesn’t have a call back function defined from product team. So we need to use the one provide as Save().Then() function.

Call the function onSave on save of button click and pass the execution context.

ServiceBusy_Error

Code which can be copied.

var isSaveClicked = false; var isSaveClicked = false; var FormTypes = { ‘Create’: 1, ‘Update’: 2 };     function onSave (context) {               if (formType === FormTypes.Create && !isSaveClicked) {            isSaveClicked = true;            context.getEventArgs().preventDefault();            MisXrmUtilities.Common.DisableField(“ABC_FieldField1”);            MisXrmUtilities.Common.DisableField(“ABC_FieldField2”);

////we need to use the timeout function so that service doesn’t get busy

setTimeout(function () {                Xrm.Page.data.save().then(function () {                }, function (error) {                    isSaveClicked = false;                    MisXrmUtilities.Common.EnableField(“ABC_FieldField1”);                    MisXrmUtilities.Common.EnableField(“ABC_FieldField2”);                });            }, 1000);        }    };

Advertisements

Plugin throw customized error, unsaved changes are on form.

I have got one issue when I change some hidden fields on the CRM form and then I was executing the save code for CRM, on save there was one plugin running that throws some handled error message. Now I only get the “OK” and “Download Log” button.

Once i click OK button i still see some unsaved changes

For that if we don’t want to show the unsaved changes on the form below things we can do.

  1. Either find what are all the fields we have changes and set their initial values once you click the okay button (Note: we don’t have any click event given for this ‘OK’) button.
  2. Or some how set the form dirty = false on close of that pop up. (That is also not possible to achieve as we don’t have click/change event)

Solution for this situation would be as below :

  1. we can use save.then() function like below:

Xrm.Page.data.save().then(function (success) {
//This is success call back , do whatever you want to do. after save is done.
}, function (error) {
Xrm.Page.getAttribute(“FieldUniqueName”).setValue(Xrm.Page.getAttribute(“FieldUniqueName”).getInitialValue());

////Please note this getInitialValue only work for optionset and bool fields.
Xrm.Page.data.setFormDirty(false);
if (error && error.message) {
//This is the section where we get the error.message in the string format, we can show this in the formnotification.
} else {
// show default message if the error.message is empty or undefined.
}
});

How to get the current datetime in CRM client side using Javascript.

I got the issue where I needed to get the datetime as per CRM logged in user timezone. I have written one more blog where we can do this at server side by hitting the org service Get date time as per current user time zone , but how to do that at client side??

Either we can hit the CRM services to get the timezone and calculate the time or we have one simple way to do that as below:

What exactly below code does?

This gets the current machine time and then converts the UTC datetime. after that we calculate crm user datetime by adding the current time zone offset minutes of logged in user.

How to get the offset minutes of the login user?

Xrm.Page.context.getTimeZoneOffsetMinutes();

////Please note: This method is available only after “CRM 2015 Update 1” version.

over all code is as below:

var date = new Date();

var utcDate = new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.getUTCMilliseconds());

var crmUserDateTime = new Date(utcDate.setMinutes(utcDate.getMinutes() + Xrm.Page.context.getTimeZoneOffsetMinutes()));

We can ever use jQuery date picker and simply pass the date in var date = new Date(“05/25/2017”);

var date = new Date(“05/25/2017”); // here we can pass multiple formated dates. and any date.

var utcDate = new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.getUTCMilliseconds());

var crmUserDateTime = new Date(utcDate.setMinutes(utcDate.getMinutes() + Xrm.Page.context.getTimeZoneOffsetMinutes()));

Hope this helps 🙂

Happy learning.

Please follow my blog, so that whenever i create any blog you get notifications.

Limitations of Microsoft dynamic CRM Word Templates

  1. It cannot Filter/Sort the repeater data.
  2. We can only go up to one level down in context of relationship.
  3. If any of the attribute value is empty then it reserves the place (template looks dirty because of empty spaces)
  4. Repeater Only shows 100 lines( if you have more than 100 contact in account it won’t show)
  5. Once the document is downloaded and later on if you add any new field you have to delete the document and create the new document, As there is no update document option. We need to remap the fields again (here copy paste works that’s one releaf point).

How to fetch Users with Security roles using fetch xml

securityroleswithusername

<fetch mapping=”logical” count=”50″ version=”1.0″ >
<entity name=”systemuser” >
<attribute name=”fullname” />
<link-entity name=”systemuserroles” from=”systemuserid” to=”systemuserid” >
<link-entity name=”role” from=”roleid” to=”roleid” >
<attribute name=”name” />
<attribute name=”roleid” />
</link-entity>
</link-entity>
</entity>
</fetch>

——————————Below fetch can be used in fetch based report———-

<fetch mapping=”logical”>
<entity name=”systemuser” >
<attribute name=”fullname” />
<attribute name=”systemuserid” />
<link-entity name=”systemuserroles” from=”systemuserid” to=”systemuserid” alias=”systemMapping” >
<link-entity name=”role” from=”roleid” to=”roleid” alias=”RoleTable” >
<attribute name=”name” />
<attribute name=”roleid” />
</link-entity>
</link-entity>
</entity>
</fetch>

 

Javascript calls action in CRM

//this function is responsible to set the headers

var setRequestHeaders = function (req, includeFormattedValues, customHeaders) {
req.setRequestHeader(“Accept”, “application/json”);
req.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);
req.setRequestHeader(“OData-MaxVersion”, “4.0”);
req.setRequestHeader(“OData-Version”, “4.0”);
if (!(includeFormattedValues !== undefined && includeFormattedValues !== null && includeFormattedValues === false)) {
req.setRequestHeader(“Prefer”, “odata.include-annotations=\”OData.Community.Display.V1.FormattedValue\””);
}

if (!(customHeaders && customHeaders.constructor === [].constructor)) {
customHeaders = [];
}
customHeaders.forEach(function (h) {
switch (h.key) {
case “Accept”:
case “Content-Type”:
case “OData-MaxVersion”:
case “OData-Version”:
case “Prefer”:
break;
default:
req.setRequestHeader(h.key, h.value);
break;
}
});
},

 

// function name
stringParameterCheck = function (parameter, message) {
if (typeof parameter !== “string”) {
throw new Error(message);
}
},

//Async function

executeCustomAction = function (entityId, entityCollectionName, actionName, parameters, isGlobleAction, successCallback, errorCallback, customHeaders) {
var query = “”, req = “”;
stringParameterCheck(actionName, “MisXrmUtilities.WebAPI.executeCustomAction requires the actionName parameter is a string.”);

if (isGlobleAction !== undefined && isGlobleAction !== null && isGlobleAction !== true) {
stringParameterCheck(entityId, “MisXrmUtilities.WebAPI.executeCustomAction requires the e entityId parameter is a string.”);
stringParameterCheck(entityCollectionName, “MisXrmUtilities.WebAPI.executeCustomAction requires the entityCollectionName parameter is a string.”);
entityId = entityId.replace(“{“, “”).replace(“}”, “”);
query = entityCollectionName + “(” + entityId + “)/Microsoft.Dynamics.CRM.” + actionName;
}
else {
query = actionName;
}

req = new XMLHttpRequest();
req.open(“POST”, getWebAPIPath() + query, true);
setRequestHeaders(req, false, customHeaders);
req.onreadystatechange = function () {
if (this.readyState == 4) {
req.onreadystatechange = null;
switch (this.status) {
case 200:
successCallback(JSON.parse(this.response));
break;
case 204:
case 1223:
successCallback();
break;
default:
errorCallback(JSON.parse(this.response).error);
break;
}

}
};

req.send((parameters !== undefined && parameters !== null) ? JSON.stringify(parameters) : null);
},

 
//==============How to use this function==================//
parametersInJsonFormate = {
ActionInputParameter1: “here is the input”, // Make sure the name maches with the action input parameters
ActionInputParameter2: “anything can be passed”
};
executeCustomAction(entityId, entityCollectionName, actionName, parametersInJsonFormate, false, function(success){
//Success call back
}, function(error){

//Error call back
});

Request message has unresolved parameters.

In CRM when you get this error while calling action. then there may be three reasons behind that

  1. some parameters you are passing wrong. (make sure action name is correctly pass)
  2. your action is not activated
  3. your action name is duplicate and one action is in active mode and other is in draft.(as this is done from CRM side that one has to be in draft only two same name action wont be active at same time.)
  4. When we use assign value step then if the step wants to return some value then we need to create one output parameter or it might give error.

 

I will talk about the 3) point. here.

to resolve this you need to delete the draft or other active actions, keep only one.

I have seen by default it will create two action in active mode. that’s fine let it  be

if it gives error while deleting your action then deactivate all the actions which we search on advance fine and then delete all and recreate.

How will you find it ???

Go to advance find and delete the default filters and put you process name contains (your action name) and you will find out there are actually two action with the same name.

How this happened in CRM???

🙂 you may have imported the actions twice in CRM.