Check highest privileges for entities from different Security roles assigned (including Teams Roles) to User in MS CRM

What is Issue?

User in CRM might be assigned with the different security roles directly or indirectly from Teams security role. Some time it becomes difficult to check privileges on some entity, due to number of different security roles assigned. In this cases, checking different security roles for user becomes tedious and time consuming task. You need to check each security role and each security roles for team in which user is member.

The Reason-

No direct way available to check highest privileges on entities for an user.

Solution-

you can use the tool created by mscrm16Tech as below-
It provides view of all security roles assigned directly or indirectly through Team to user.

When you install and open the application in your system you will get below window which will help you in configuration of MS CRM connection and database connection if needed.

AppScreen1

After configuring the app and clicks on OK, Select the application “Check User Privileges on Entity” in next window  –

App3Screen0

Now you need to load the available active (Enabled) users in connected CRM Organization.
You can select any user from the drop down list and get Privileges for the user.

You also have option to check security roles for entities for some publisher only(custom entities).

The output loaded in grid will show highest privileges on entities available to user cumulatively from all security security roles.

Please use below image for reference-

App3Screen1

Please follow the images to work with the app.

You can find the list of all available security roles assigned directly or indirectly through teams to user.

On click of first option in List -“Get Cumulative privileges for all Roles”  will show the all highest privileges from all the different security roles. and on click of other options in list will show the privileges for that role.

You can save this report as excel file.

You can download MSCRMTechTool Here- MSCRM16Tech Tool

Hope this will help…
Enjoy Ms CRM!!!

Follow on Facebook- FB: MSCRM16Tech

 

Generating Early Bound Classes and simple Entity Classes MS CRM

What is Issue?

While developing the CRM, when we have to go through coding part, we need to create Early-bound classes for some specific entities. But CrmSvcUtil.exe provides us the Early Bound classes for all the entities available in CRM.
Second scenario- we don’t want this much of complicated classes, Only want to add simple Entity classes. But it might become very lengthy and time consuming task to add the fields in class one by one.

The Reason-

Creating Early bound classes for particular entities is not possible using CrmSvcUtil.exe directly and creating simple entity classes is lengthy and time consuming task.

Solution-

To create early bound classe using CrmSvcUtil.exe, please refer blog – Generate Early Bound Classes for selected entities using CrmSvcUtil.exe in MS CRM

OR

you can use the tool created by mscrm16Tech as below-
It provides both the options like creating Simple CRM entity classes or to Use CrmSvcUtil.exe to generate early bound classes for selected entities only.

When you install and open the application in your system you will get below window which will help you in configuration of MS CRM connection and database connection if needed.

AppScreen1

After configuring the app and clicks on OK, Select the application “Create Early-Bound Classes” in next window  –

App2Screen0

Now you can load the available entities in connected CRM Organization. Please use below image for reference-

App2Screen In case you are using windows 10 and trying to generate Early Bound classes using CrmSvcUtil.exe, you need to make sure following feature is enabled on your windows-
>Control Panel Programs and Features – Turn Windows feature On or Off
->.NetFramework 4.8 Advanced Services
-> WCF Services
->HTTP Activation (Please enable if not)

App2Screen1

Please follow the images to work with the app.

You can download app Here- MSCRM16Tech Tool

Hope this will help…
Enjoy Ms CRM!!!

Follow on Facebook- FB: MSCRM16Tech

 

Get Excel Report or Create Database table Directly from FetchXML file

What is Issue?

The creating report or database table using complex fetchXML and getting records more than 5000.

The Reason-

It is difficult to get data directly from MS CRM without any coding or using third party tool .

Solution-

Here is the new tool created by mscrm16tech which allows you to save data in excel sheet from MS CRM or helps you to create Database table with the display names available in MS CRM. These reports and data dump minimizes the developer efforts.

When you install and open the application in your system you will get below window which will help you in configuration of MS CRM connection and database connection if needed.

AppScreen1

After configuring the app and clicks on OK, you will get below window –

AppScreen2

Please follow the images to work with the app.

You can download app Here- FetchApp by MSCRM16Tech

Hope this will help…
Enjoy Ms CRM!!!

Follow on Facebook- FB: MSCRM16Tech

 

Call MS CRM Web API outside CRM Applicaiton or with Postman

What is Issue?

MS CRM provides out-of-box Web API which we mostly use in javascript to get data from entities whenever required. But there are many situations where your company uses different applications and CRM is one of them. The data across company can be used in any of these application in real time. So instead of writing custom Web API, if MS CRM provides out-of-box Web API, can we use that in any other application? or is it possible to call MS CRM APIs using postman for testing purpose before used in any other application?

The Reason-

MS CRM provides the way to get data from entities with calling Web API. But mostly we use this API calls within CRM application. When calling Web API within CRM , user is already logged in to the CRM which do not need any extra authorization. When we try to calls these Web API out side CRM it requires authorization to access data from CRM.

Solution-

To Call Web APIs outside MS CRM environment you need to get Bearer token for the user using OAuth2.0 authorization.

Lets take example – WebAPI to get all Accounts- https://xxxxx.crm8.dynamics.com/api/data/v8.2/accounts

Lets generate bearer token to access above WebAPI from Postman-
I am considering You have registered the Azure app and you have Client Id and Client secrete with you for this app.
In Postman- New request add your request –

    1. Go to the Authorization tab
    2. Select Type – OAuth2.0
    3. Click on Get New Access TokenPostMan0
    4. In popup window please enter all required information as below-PostMan
    5. Grant Type – Authorization Code
    6. Enter Callback URL provided in Azure App – Redirect URI
    7. Enter Auth URL –
      https://login.windows.net/common/oauth2/authorize?resource=https://xxxxx.crm8.dynamics.com
    8. Access Token URL –
      https://login.microsoftonline.com/common/oauth2/token
    9. Enter Client Id and Client Secret you have.(Azure App client details).
    10. Click on Request Token.
    11. Microsoft login window will popup. Enter your credentials to login.On successful authentication, It will bring an access token for you.
    12. Select Access Token you have generated just a while before from Available tokens in postman.
    13. Don’t forget to select Add authorization data to – Request HeaderPostMan2
    14. Now you can send the request and test your MS CRM Web APIs.
    15. You can use the Code option in postman to generate code according to your programming needs.PostMan3

You can use the same parameters when generating bearer token for the user using code.

How to get bearer token using Postman-

  1. Use Post Method and URL-
    https://login.microsoftonline.com/common/oauth2/token
  2. Add below details to Body of the request as form-data-
    – grant_type – client_credentials
    – user’s credentials : username and password
    – other details – client_id and client_secret as described above. -resource : your MS CRM url.
  3. PostMan4

Using the bearer token generated you can access MS CRM Web APIs in any application.

Hope this will help…
Enjoy Ms CRM!!!

Follow on Facebook- FB: MSCRM16Tech

Date Time issue due to different Timezone of User in MS CRM

What is Issue?

Working with date time field is most challenging task in MS CRM. Many times user sees the Date time in record which is different on the email he received or on some where it is populated and he reports the issue. Date time on the records should be consistent through out the MS CRM application. If record is used on some other entity or web-resource with that date time field, It should be exactly matching to the actual date time on record which is visible to user.

The Reason-

The reason behind this issue on timezone of the user and CRM application. At the time of execution of some server side code, it will always give you the date time in CRM server timezone. And if CRM application is going to used wordwide or from multiple timezones these date time fields might show mismatch data.

Solution-

One solution for this is to make all the user time zone similar to the server timezone. But when any javascript populates some date time field this might cause wrong date time.

Example: User is working from India and the Crm Server is placed in UK. User sets his timezone to UK timezone. but if any javascript is populating current date and time in record it will be Indian time which will be +5.30 hrs ahead. This data created is wrong at this time.

Another solution is to handle this date time things in code itself.

In Code we can perform following steps-

  1. Get user’s personal setting like – date time form, timezone information, locale informtion.
  2. Convert date time according to user setting.
  3. format this date time in user setting format.
  4. Set this updated date time on your desired place.

Now in both server side and client side how to handle it?

Server side code

Server side you need only 2 requests –

  1. LocalTimeFromUtcTimeRequest
  2. UtcTimeFromLocalTimeRequest

And UserSettings entity for Timezone Code.

using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;

namespace TestConsoleApp
{
    class TestLogic
    {
        int? _timeZoneCode = 83;
        public void YourLogic(IOrganizationService service, Object parameter = null) {
            //get user's timezone-
            _timeZoneCode = RetrieveUsersTimeZoneCode(service);
            
            //datetime Value 
            DateTime scheduledStartDate=DateTime.Now;
            Console.WriteLine(scheduledStartDate.ToString());
         
            //Convert to User Local Time
            DateTime dt =scheduledStartDate.ToUniversalTime();
            DateTime UserLocalTime=RetrieveLocalTimeFromUTCTime(service, dt,_timeZoneCode);

            //convert to server Time
            DateTime serverTime =RetrieveUTCTimeFromLocalTime(service, UserLocalTime, _timeZoneCode);
            
            Console.Read();
        }

        public int? RetrieveUsersTimeZoneCode(IOrganizationService service, EntityReference user = null)
        {

            ConditionExpression cd = null;
            if (user == null)
                cd = new ConditionExpression("systemuserid", ConditionOperator.EqualUserId);
            else
                cd = new ConditionExpression("systemuserid", ConditionOperator.Equal, user.Id);

            var currentUserSettings = service.RetrieveMultiple(
            new QueryExpression("usersettings")
            {
                ColumnSet = new ColumnSet("localeid", "timezonecode"),
                Criteria = new FilterExpression
                {
                    Conditions = { cd }
                }
            }).Entities[0].ToEntity();
            return (int?)currentUserSettings.Attributes["timezonecode"];
        }

        public DateTime RetrieveLocalTimeFromUTCTime(IOrganizationService service, DateTime utcTime, int? timeZoneCode)
        {
            if (!timeZoneCode.HasValue)
                return utcTime;

            var request = new LocalTimeFromUtcTimeRequest
            {
                TimeZoneCode = timeZoneCode.Value,
                UtcTime = utcTime.ToUniversalTime()
            };

            var response = (LocalTimeFromUtcTimeResponse)service.Execute(request);

            return response.LocalTime;
        }

        public DateTime RetrieveUTCTimeFromLocalTime(IOrganizationService service, DateTime localTime, int? timeZoneCode)
        {
            if (!timeZoneCode.HasValue)
                return DateTime.Now;

            var request = new UtcTimeFromLocalTimeRequest
            {
                TimeZoneCode = timeZoneCode.Value,
                LocalTime = localTime
            };

            var response = (UtcTimeFromLocalTimeResponse)service.Execute(request);
            return response.UtcTime;
        }
    }
}

Client side code

In Javascripts, You need to play around UserSettings, LanguageLocale, TimezoneDefinition entities.

//array of all unique timezone offsets
var allTimeZones = { "(GMT+01:00)": "Africa/Algiers", "(GMT+02:00)": "Europe/Tirane", "(GMT+03:00)": "Europe/Mariehamn", "(GMT+04:00)": "Asia/Yerevan", "(GMT+04:30)": "Asia/Kabul", "(GMT+05:00)": "Antarctica/Mawson", "(GMT+05:30)": "Asia/Kolkata", "(GMT+05:45)": "Asia/Kathmandu", "(GMT+06:00)": "Antarctica/Vostok", "(GMT+06:30)": "Indian/Cocos", "(GMT+07:00)": "Antarctica/Davis", "(GMT+08:00)": "Antarctica/Casey", "(GMT+08:45)": "Australia/Eucla", "(GMT+09:00)": "Asia/Dili", "(GMT+09:30)": "Australia/Adelaide", "(GMT+10:00)": "Antarctica/DumontDUrville", "(GMT+10:00)": "Australia/Brisbane", "(GMT+10:30)": "Australia/Lord_Howe", "(GMT+11:00)": "Antarctica/Macquarie", "(GMT+12:00)": "Antarctica/McMurdo", "(GMT+12:45)": "Pacific/Chatham", "(GMT+13:00)": "Pacific/Enderbury", "(GMT+14:00)": "Pacific/Kiritimati", "(GMT-01:00)": "Atlantic/Cape_Verde", "(GMT-02:00)": "America/Noronha", "(GMT-02:30)": "America/St_Johns", "(GMT-03:00)": "Antarctica/Palmer", "(GMT-04:00)": "America/Anguilla", "(GMT-05:00)": "America/Eirunepe", "(GMT-06:00)": "America/Belize", "(GMT-07:00)": "America/Creston", "(GMT-08:00)": "Pacific/Pitcairn", "(GMT-09:00)": "Pacific/Gambier", "(GMT-09:30)": "Pacific/Marquesas", "(GMT-10:00)": "Pacific/Rarotonga", "(GMT-11:00)": "Pacific/Pago_Pago", "(GMT)": "Africa/Lome" };

//call this function to get user date in concerted format.
var GetTimeInCurrentUserZoneAndFormat=function(xrm,new_startdate) {
    //example : I have fetched new_startdate using REST Api and  new_startdate = 2019-08-30T10:00:00+01:00  
    var d = new Date(new_startdate);
    //step 1: Get user Date and Time format which he selected in Personal settings of CRM
    var dtFormat = GetDateandTimeSettingsOfUser(xrm);
    //step 2: convert Date to user local date.
    var userLocalDate = convertTimetoSpecificTimeZone(xrm, dtFormat.timeZone, dtFormat.localeId)
    // step 3: now convert date time format in user format 
    var convertedDateTime = ConvertDateInFormat(d, dtFormat.dateformat, dtFormat.dSeparator, dtFormat.timeFormat, dtFormat.tSeparator);

    return convertedDateTime; 
}

//get user's personal setting 
var GetDateandTimeSettingsOfUser = function (xrm) {
    var recordId = xrm.Page.context.getUserId();
    recordId = recordId.replace(/[{}]/g, "");
    var format = { dateformat: null, dSeparator: null, timeFormat: null, tSeparator: null, timeZone: null, localeId: null };
    var req = new XMLHttpRequest();
    req.open("GET", xrm.Page.context.getClientUrl() + "/api/data/v9.0/usersettingscollection?$select=dateformatstring,dateseparator,timeformatstring,timeseparator,localeid,timezonecode&$filter=systemuserid eq " + recordId, false);
    req.setRequestHeader("OData-MaxVersion", "4.0");
    req.setRequestHeader("OData-Version", "4.0");
    req.setRequestHeader("Accept", "application/json");
    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    req.setRequestHeader("Prefer", "odata.include-annotations=\"*\"");
    req.onreadystatechange = function () {
        if (this.readyState === 4) {
            req.onreadystatechange = null;
            if (this.status === 200) {
                var results = JSON.parse(this.response);
                for (var i = 0; i < results.value.length; i++) {
                    format.dateformat = results.value[i]["dateformatstring"];
                    format.dSeparator = results.value[i]["dateseparator"];
                    format.timeFormat = results.value[i]["timeformatstring"];
                    format.tSeparator = results.value[i]["timeseparator"];
                    format.localeId = results.value[i]["localeid"];
                    format.timeZone = results.value[i]["timezonecode"];
                }
            }
            else {
                Xrm.Utility.alertDialog(this.statusText);
            }
        }
    };
    req.send();
    return format;
}

//start converting time to user local time
var convertTimetoSpecificTimeZone = function (xrm, date, _timezonecode, _localeid) {
    var timeZoneName = getTimeZoneStandartName(xrm, _timezonecode);
    var localeCode = getLocaleCode(xrm, _localeid);

    var GMTCode = timeZoneName.uiName.substring(0, 11);


    var newDate = date.toLocaleString(localeCode, { timeZone: allTimeZones[GMTCode] });

    return newDate;

}
var getTimeZoneStandartName = function (xrm, _timezoneCode) {
    var TimeZoneName = { standardName: "Greenwich Standard Time", uiName: "(GMT+00:00) Monrovia, Reykjavik" }
    var req = new XMLHttpRequest();
    req.open("GET", xrm.Page.context.getClientUrl() + "/api/data/v9.0/timezonedefinitions?$select=standardname,timezonecode,userinterfacename&$filter=timezonecode eq " + _timezoneCode, false);
    req.setRequestHeader("OData-MaxVersion", "4.0");
    req.setRequestHeader("OData-Version", "4.0");
    req.setRequestHeader("Accept", "application/json");
    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    req.setRequestHeader("Prefer", "odata.include-annotations=\"*\"");
    req.onreadystatechange = function () {
        if (this.readyState === 4) {
            req.onreadystatechange = null;
            if (this.status === 200) {
                var results = JSON.parse(this.response);
                for (var i = 0; i < results.value.length; i++) {
                    TimeZoneName.standardName = results.value[i]["standardname"];
                    TimeZoneName.uiName = results.value[i]["userinterfacename"];
                }
            } else {
                xrm.Utility.alertDialog(this.statusText);
            }
        }
    };
    req.send();
    return TimeZoneName;
}


var getLocaleCode = function (xrm, _localeId) {
    var code = "en-us";
    var req = new XMLHttpRequest();
    req.open("GET", xrm.Page.context.getClientUrl() + "/api/data/v9.0/languagelocale?$select=code,localeid&$filter=localeid eq " + _localeId, false);
    req.setRequestHeader("OData-MaxVersion", "4.0");
    req.setRequestHeader("OData-Version", "4.0");
    req.setRequestHeader("Accept", "application/json");
    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    req.setRequestHeader("Prefer", "odata.include-annotations=\"*\"");
    req.onreadystatechange = function () {
        if (this.readyState === 4) {
            req.onreadystatechange = null;
            if (this.status === 200) {
                var results = JSON.parse(this.response);
                for (var i = 0; i < results.value.length; i++) {
                    code = results.value[i]["code"];
                    var localeid = results.value[i]["localeid"];
                    var localeid_formatted = results.value[i]["localeid@OData.Community.Display.V1.FormattedValue"];
                }
            } else {
                xrm.Utility.alertDialog(this.statusText);
            }
        }
    };
    req.send();
    return code;
}

//to convert date time in particular format use the below function
//You can add more cases if you required more formats.	
var ConvertDateInFormat = function (date, dateFormat, dateSeperator, timeformat, timeSeperator) {
    if (dateFormat === void 0) { dateFormat = "M/d/yyyy"; }
    if (dateSeperator === void 0) { dateSeperator = "/"; }
    if (timeformat === void 0) { timeformat = "HH:mm"; }
    if (timeSeperator === void 0) { timeSeperator = ":"; }
    var daysShortW = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
    var daysLongW = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
    var monthLongW = ["January", "February", "March", "April", "May", "june", "July", "August", "September", "October", "November", "December"];
    var monthShortW = ["Jan", "Feb", "Mar", "Apr", "May", "jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"];
    var M = date.getMonth();
    var dd = date.getDate();
    var y = date.getFullYear();
    var day = date.getDay();
    var H = date.getHours();
    var m = date.getMinutes();
    var s = date.getSeconds();
    var ms = date.getMilliseconds();
    var formatedDateTime = date.toLocaleString();
    var formattedDateString = "";
    var formattedTimeString = "";
    switch (dateFormat) {
        case "MM/dd/yyyy":
            var dt = "" + dd;
            if (dt.length < 2)
                dt = '0' + dt;
            var month = "" + (M + 1);
            if (month.length < 2)
                month = '0' + month;
            formattedDateString = [month, dt, "" + y].join(dateSeperator);
            break;
        case "dd/MM/yyyy":
            var dt = "" + dd;
            if (dt.length < 2)
                dt = '0' + dt;
            var month = "" + (M + 1);
            if (month.length < 2)
                month = '0' + month;
            formattedDateString = [dt, month, "" + y].join(dateSeperator);
            break;
        case "M/d/yyyy":
            formattedDateString = ["" + (M + 1), "" + dd, "" + y].join(dateSeperator);
            break;
        case "dd/MMM/yy":
            var dt = "" + dd;
            if (dt.length < 2)
                dt = '0' + dt;
            var year = "" + y;
            year = year.substring(2, 4);
            formattedDateString = [dt, monthShortW[M], year].join(dateSeperator);
            break;
        case "M/d/yy":
            var year = "" + y;
            year = year.substring(2, 4);
            formattedDateString = ["" + (M + 1), "" + dd, year].join(dateSeperator);
            break;
        case "d/M/yy":
            var year = "" + y;
            year = year.substring(2, 4);
            formattedDateString = ["" + dd, "" + (M + 1), year].join(dateSeperator);
            break;
        case "MM/dd/yy":
            var dt = "" + dd;
            if (dt.length < 2)
                dt = '0' + dt;
            var month = "" + (M + 1);
            if (month.length < 2)
                month = '0' + month;
            var year = "" + y;
            year = year.substring(2, 4);
            formattedDateString = [month, dt, year].join(dateSeperator);
            break;
        case "dd/MM/yy":
            var dt = "" + dd;
            if (dt.length < 2)
                dt = '0' + dt;
            var month = "" + (M + 1);
            if (month.length < 2)
                month = '0' + month;
            var year = "" + y;
            year = year.substring(2, 4);
            formattedDateString = [dt, month, year].join(dateSeperator);
            break;
        case "yy/MM/dd":
            var dt = "" + dd;
            if (dt.length < 2)
                dt = '0' + dt;
            var month = "" + (M + 1);
            if (month.length < 2)
                month = '0' + month;
            var year = "" + y;
            year = year.substring(2, 4);
            formattedDateString = [year, month, dt].join(dateSeperator);
            break;
        case "yyyy/MM/dd":
            var dt = "" + dd;
            if (dt.length < 2)
                dt = '0' + dt;
            var month = "" + (M + 1);
            if (month.length < 2)
                month = '0' + month;
            formattedDateString = ["" + y, month, dt].join(dateSeperator);
            break;
    }
    var hours = "" + H;
    if (hours.length < 2)
        hours = "0" + hours;
    var minutes = "" + m;
    if (minutes.length < 2)
        minutes = "0" + minutes;
    switch (timeformat) {
        case "HH:mm":
            formattedTimeString = [hours, minutes].join(timeSeperator);
            break;
        case "H:mm":
            formattedTimeString = ["" + H, minutes].join(timeSeperator);
            break;
        case "hh:mm tt":
            var td = hours + ":" + minutes + ":00";
            formattedTimeString = this.timeConvertToAMPM(td, "hh:mm tt");
            break;
        case "h:mm tt":
            var td = hours + ":" + minutes + ":00";
            formattedTimeString = this.timeConvertToAMPM(td, "h:mm tt");
            break;
    }
    if (formattedDateString != "") {
        if (formattedTimeString != "")
            formatedDateTime = formattedDateString + " " + formattedTimeString;
        else
            formatedDateTime = formattedDateString;
    }
    else {
        if (formattedTimeString != "")
            formatedDateTime = formattedTimeString;
    }
    return formatedDateTime;
}

//convert time string to AMPM format
var timeConvertToAMPM = function (time, format) {
    var patt = new RegExp("^([01]?[0-9]|2[0-3]):?[0-5][0-9](:[0-5][0-9])?$");
    var res = patt.test(time);
    if (res) { // If time format correct
        var H = +time.substr(0, 2);
        var h = (H % 12) || 12;
        var hour = "" + h;
        var ampm = H < 12 ? "AM" : "PM";
        if (format == "hh:mm tt")
            if (hour.length < 2)
                hour = "0" + hour;
        time = hour + time.substr(2, 3) + " " + ampm;
    }
    return time;
};

Hope this will help…

Enjoy Ms CRM!!!

Follow on Facebook- FB: MSCRM16Tech