Sunday, 23 October 2016

Show-Hide Section on the Basis of Security Role of Current User Using Javascript in MS Dynamics CRM

Show-Hide Section on the Basis of Security Role of Current User Using Javascript in MS Dynamics CRM
Show Fields on the Basis of Security Role of Current User Using Javascript in MS Dynamics CRM

Sometimes, we face such situation where we want to show some specific section to users having a specific role only.

Scenario: Let's say on case form you want to show a "Details" section under "general" tab only to the user having "CSR Manager" role.

Now,it can be achieved using Javascript easily using below code:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Function Show-Hide a section based on a particular Role
function ShowHideSectionAccordingToRole()
{

if(CheckCurrentUserRole("CSR Manager"))
{
//Show the section
ToggleSection("general","Details",true);
}
else 
{
//Hide the section
ToggleSection("general","Details",false);
}
}

//Function to Show-Hide a section in Specific Tab
//Parameters
//TabName - Name of the Tab in Which the Section Exist
//SectionName - Name of the Section you want to Show-Hide
//Flag - true to Show and false to hide section
function ToggleSection(TabName, SectionName, Flag)
{       
    Xrm.Page.ui.tabs.get(TabName).sections.get(SectionName).setVisible(Flag);
}


//Check login User has role passed through Parameter
//Parameter
//IsRole - Name of the Role you want current user to check for
//Return Type - Boolean, True if User have that Role ,False if user doesn't have that Role
function CheckCurrentUserRole(IsRole) {
    var currentUserRoles = Xrm.Page.context.getUserRoles();
    for (var i = 0; i < currentUserRoles.length; i++) 
{
         var userRoleId = currentUserRoles[i];
         var userRoleName = GetRoleName(userRoleId);
         if (userRoleName == IsRole) 
   return true;
    }
    return false;
}

//Get Role-name based on RoleId
function GetRoleName(roleId) {
var serverUrl = Xrm.Page.context.getClientUrl();
var odataSelect = serverUrl + "/XRMServices/2011/OrganizationData.svc" + "/" + "RoleSet?$filter=RoleId eq guid'" + roleId + "'";
    var roleName = null;
    $.ajax(
        {
            type: "GET",
            async: false,
            contentType: "application/json; charset=utf-8",
            datatype: "json",
            url: odataSelect,
            beforeSend: function (XMLHttpRequest) { XMLHttpRequest.setRequestHeader("Accept", "application/json"); },
            success: function (data, textStatus, XmlHttpRequest) {
                roleName = data.d.results[0].Name;
            },
            error: function (XmlHttpRequest, textStatus, errorThrown) { alert('OData Select Failed: ' + textStatus + errorThrown + odataSelect); }
        }
    );
    return roleName;
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



Show Fields on the Basis of Security Role of Current User Using Javascript in MS Dynamics CRM

If you want to show/Hide or Lock/Unlock specific field instead of a whole section you can just replace the "ShowHideSectionAccordingToRole" function with the below function :

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function ShowHideFieldAccordingToRole()
{

if(CheckCurrentUserRole("CSR Manager"))
{
//Show the Field
Xrm.Page.ui.controls.get("FieldName").setVisible(true);
               //To UnLock the field
              // Xrm.Page.getControl("FieldName").setDisabled(false); 
}
else 
{
//Hide the Field
Xrm.Page.ui.controls.get("FieldName").setVisible(false);
               //To lockLock the field
              // Xrm.Page.getControl("FieldName").setDisabled(true); 
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Some may argue that why would we use javascript to show/hide field when we have field security profiles.
I agree we have field security profiles which have much more feature to control over a field but here Javascript  is also an easy way to handle this.

I hope it would be helpful. 
Comments are highly appreciated.

Happy CRM...!!!

Monday, 12 September 2016

Open Specific Form Using javascript in Dynamics CRM

Open Specific Form of any entity Using javascript in Dynamics CRM


In this post we'll learn how we can open a specific type of form of an entity using javascript.

Scenario: Let's say you have 2 different main form of phone call entity. You want to open specific form on the basis of specific attribute on the form. 

Here in this case we have a Call Type option set. On the basis of which use wants to open different form. For instance vales of Call Type may be Sales/Service and user wants to open new form of sales of phone call when he selects sales in option set and want to open main form of service of phone call if he selects service, he can implement the same using javascript as below:

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  function ChoosePage()
{
var CallType = Xrm.Page.getAttribute("new_calltype").getValue();
if(CallType!=null)
{
   var FormId;
if (CallType==1) //Sales
{
FormId='78958D5A-FE73-45E8-8F78-950B1389BE2E';
}
else if (CallType==2) //Service
{
   FormId='A91390A5-99BB-4D10-9EEE-3A5C87F841F1';  
var parameters = {};
parameters["formid"] = FormId;
parameters["new_calltype"] = CallType;
Xrm.Utility.openEntityForm("phonecall", null, parameters);
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Here "null" signify that we are opening a new form.

If you want to open existing record in different form then you can pass Guid of that record.

* We can pass as many objects in parameter as we want which will come pre-set in the new form opened.

* The formid used in the code can be found in Customization->Entity->Forms

Hope it's helpful.


Suggestions and comments are highly appreciated.

Happy CRM...!


Tuesday, 16 August 2016

MS CRM Error: The Entity Relationship with SchemaName = '" was not found in the MetadataCache

MS CRM Error: The Entity Relationship with SchemaName = '" was not found in the MetadataCache


Recently i was having this issue while opening any existing account record or creating a new account record in a CRM org.
Error message: The Entity Relationship with SchemaName = '" was not found in the MetadataCache

Log file
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=8.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: System.Web.HttpUnhandledException: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #D985AF1CDetail: 
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
  <ErrorCode>-2147220970</ErrorCode>
  <ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
  <Message>System.Web.HttpUnhandledException: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #D985AF1C</Message>
  <Timestamp>2016-08-16T06:57:30.9208191Z</Timestamp>
  <InnerFault>
    <ErrorCode>-2147220918</ErrorCode>
    <ErrorDetails xmlns:d3p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
    <Message>The Entity Relationship with SchemaName = 'new_account_new_orderproduct_CustomerName' was not found in the MetadataCache</Message>
    <Timestamp>2016-08-16T06:57:30.9208191Z</Timestamp>
    <InnerFault i:nil="true" />
    <TraceText i:nil="true" />
  </InnerFault>
  <TraceText i:nil="true" />
</OrganizationServiceFault>

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Now what i had done is that on a custom entity order product, i had created a lookup of account entity. (Oh please don't ask why we created custom entity named order product..!)

Also on account record, i have attached a grid of all order products (custom entity) using that lookup of account i created on custom order product entity.

Now the issue start occurring when i deleted the lookup of customer entity from custom order product entity.

I forget that relationship formed from this lookup has been used in that grid on account form.

Now whenever i tried to open main crm form (existing account or a new one) system throw the above error.

It'll off-course throw this error because metadata on account form have the reference to such a relationship which doesn't exist any more..!

So to fix this what i did is, i removed the grid of custom order product entity from account entity which was referring a relationship which doesn't exist anymore.

So the thing we learn from this is that whenever we are deleting a lookup we should keep in mind that we are also deleting the relationship associated with it.

And if that relationship is used anywhere else, for this case in a grid, system will always create an issue.


Hope it would be helpful.
Feel free to comment and improve.

Sunday, 14 August 2016

MS CRM error: 1 is not a valid status code for state code SalesOrderState

1 is not a valid status code for state code SalesOrderState.Submitted on salesorder with Id <Guid>


Error Code -2147187704

Today i face the error on while creation of sales order in Dynamics CRM online 2016. System wasn't letting the user create sales order and throwing a generic exception with message :

1 is not a valid status code for state code SalesOrderState.Submitted on salesorder with Id <Guid>

with error code: -2147187704.

This was pretty unusual because i know that 1 is a valid status code code for sales order.

After much research, the solution i found was then relatively easy. For the user the indicator "Integration Users Mode" in the user administration was switched to Yes. 

But the problem was this flag isn't usually displayed on the CRM user form.
So here i used little trick. I created a on demand workflow to set back the field to NO and run the on demand workflow on the user.  

After I put this flag back to No everything was working as per the expectations.

My observation is that recently the user had experimented with the CRM connectors to connect the CRMs with Navision, while the flag was changed by the Connector.


Hope it would be helpful.
Please comment if any better solution exist.