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

Hide Entities from Advanced Find List – MS CRM

What is Issue?

Ms CRM provides the way to query the records in system with or without some filter criteria. There might be some conditions where we need to restrict user from querying for the entity, but still we want to have read privilege to the entity so that we can provide the visibility to the records in some desire areas. But the MS Dynamics CRM don’t have any separate option to hide/show the entities in Advanced find.

The Reason-

Ms CRM handles the entities to be visible in advanced find using Security Role. If Any entity don’t have read privilege for the security role, the entity will be hidden in advanced find for that security role. This is internally handled by “IsValidForAdvancedFind” read-only flag.

Solution-

There are multiple solution to make entity hidden from advanced find like –
A. Security Role
B. Database Query
C. RetrieveMultiple Message Override
D. Custom Code

A. Security Role –

Remove the read privilege for security Role you want to hide entity. But this security role will don’t have any read permission for the entity Records.

B. Database Query –

If you have on-premise setup, you will have database control.
So you can make “IsValidForAdvancedFind” flag False to make entity hidden in advanced find only.

C. RetrieveMultiple Message Override –

This is the simple and reliable way to make records available to the user. Create the plugin for the entity with the modified query, so that user will have visibility to the records by default which you set. This will affect overall application i.e. in subgrids, home view and where ever the retrievemultiple is called.
But this is not suitable for our requirement i.e. Hiding Entity from advanced find without any access changes to the records.

D. Custom Code – Javascript

The way I found is very easy. Within few steps you can achieve it.

Let’s say I want to hide Account and Contact entity from Advanced find.

This slideshow requires JavaScript.

1.Create a new solution with component “Application Ribbon” in it.

AFHideEntities0

2. Create a New Javacript webresource with below Code-
in my case – Name and Display Name – “mct_/Scripts/AdvancedFind.js”

//entities to be hidden
var entities = [
    'account',//Account
    'contact',//Contact
    ];
//slctPrimaryEntity is id of dropdown for entities displayed in Advanced Find.
function hideEntities() {
    var select = $("#slctPrimaryEntity");
    if (select.length > 0) {
        for(var i = 0; i < entities.length; i++)
            $("#slctPrimaryEntity option[value='" + entities[i] + "']").remove();
    }
    //find and hide button which we are going to create in next step.
    var button = window.top.document.getElementById("new.ApplicationRibbon.Button.RemoveEntities-Large");
    if (button !== undefined && button != null) button.style.display = "none";
    return false;
}

3. Open your new solution in Ribbon Workbench.

4. You will find the set of commands which are used in Advanced find. Add new button with minimum information, next to the “DOWNLOAD FETCHXML” button or at the end of this group.

ID : new.ApplicationRibbon.Button.RemoveEntities

AFHideEntities8

AFHideEntities5

5.Create a Command

ID : new.ApplicationRibbon.Command.RemoveEntities
add this command in newly added button :
Command :- new.ApplicationRibbon.Command.RemoveEntities
CommandCore :- new.ApplicationRibbon.Command.RemoveEntities

6. Add Enable Rule to the Command –

AFHideEntities6

Enable rule details-

ID : new.ApplicationRibbon.EnableRule.RemoveEntities

Add Custom Rule :-

Default - True
Function Name - hideEntities (our custom Javacsript function name)
Library - $webresource:mct_/Scripts/AdvancedFind.js  (our custom Javascript)

AFHideEntities7

7. Publish the Solution.

And Done.

You can check advanced find – There is no Account and Contact entities available.

This slideshow requires JavaScript.

Hope this will help…

Enjoy Ms CRM!!!

Follow on Facebook- FB: MSCRM16Tech

Generate Early Bound Classes for selected entities using CrmSvcUtil.exe in MS CRM v9.x

What is Issue?

There is CrmSvcUtil.exe to generate early bound entity classes. But this utility generates the classes for all the entities in the organization. But these entities are not required all the time. So how to generate classes for selected entities.

The Reason-

The Microsoft provided the CrmSvcUtil.exe utility in Microsoft.crmsdk.coretools which is used to generate early bound classes for entities, but there is no option to select particular entity or entities.

Solution-

CrmSvcUtil.exe is available in Microsoft.crmsdk.coretools package and you can download this package from nuget.

The simple solution is provided by Erik Pool for Ms CRM 2011 and this will work D365 CRM v9.x as well. Just follow the below –

Create a new C# class library project in Visual Studio called SvcUtilFilter.

Add the below assemblies to your class Library-

svcUtil1

Important reference is – CrmSvcUtil.exe
– This exe has interface ICodeWriterFilterService which needs to be implemented.
– Microsoft.Xrm.Sdk is mandatory
– Microsoft.Xrm.Tooling.Connector is important in case of v9.x.
– If you want to connect to your organization by interactive UI add
Microsoft.Xrm.Tooling.Ui.Styles and Microsoft.Xrm.Tooling.CrmConnectControl.

Add the following class to the project:

using System;
using System.Collections.Generic;
using System.Xml.Linq;
using Microsoft.Crm.Services.Utility;
using Microsoft.Xrm.Sdk.Metadata;

namespace SvcUtilFilter
{
/// CodeWriterFilter for CrmSvcUtil that reads list of entities from an xml file to
/// determine whether or not the entity class should be generated.
public class CodeWriterFilter : ICodeWriterFilterService
{
//list of entity names to generate classes for.
private HashSet _validEntities = new HashSet();

//reference to the default service.
private ICodeWriterFilterService _defaultService = null;

/// constructor
public CodeWriterFilter(ICodeWriterFilterService defaultService)
{
this._defaultService = defaultService;
LoadFilterData();
}

/// loads the entity filter data from the filter.xml file
private void LoadFilterData()
{
XElement xml = XElement.Load("filter.xml");
XElement entitiesElement = xml.Element("entities");
foreach (XElement entityElement in entitiesElement.Elements("entity"))
{
_validEntities.Add(entityElement.Value.ToLowerInvariant());
}
}

/// /Use filter entity list to determine if the entity class should be generated.
public bool GenerateEntity(EntityMetadata entityMetadata, IServiceProvider services)
{
return (_validEntities.Contains(entityMetadata.LogicalName.ToLowerInvariant()));
}

//All other methods just use default implementation:

public bool GenerateAttribute(AttributeMetadata attributeMetadata, IServiceProvider services)
{
return _defaultService.GenerateAttribute(attributeMetadata, services);
}

public bool GenerateOption(OptionMetadata optionMetadata, IServiceProvider services)
{
return _defaultService.GenerateOption(optionMetadata, services);
}

public bool GenerateOptionSet(OptionSetMetadataBase optionSetMetadata, IServiceProvider services)
{
return _defaultService.GenerateOptionSet(optionSetMetadata, services);
}

public bool GenerateRelationship(RelationshipMetadataBase relationshipMetadata, EntityMetadata otherEntityMetadata, IServiceProvider services)
{
return _defaultService.GenerateRelationship(relationshipMetadata, otherEntityMetadata, services);
}

public bool GenerateServiceContext(IServiceProvider services)
{
return _defaultService.GenerateServiceContext(services);
}
}
}

Build the project.

Next step to create XML which specifies the entities names for which you want to have early bound class.

Create filter.xml file with below structure-

<filter>

<entities>

<entity>account</entity>

<entity>contact</entity>

</entities>

</filter>

To add entity same way in this XML to create early bound class for it.

Add this filter.xml in same build folder debug/bin i.e. where the CrmSvcUtil.exe and all the other references located.

Now your build folder should be look like this-

svcUtil3

Your tool is ready now.

How to run this?
Open Command prompt. Change directory to the bin folder and run below command-

crmsvcutil.exe /url:http://your_org_url/XrmServices/2011/Organization.svc /out:output.cs /namespace: /il /codewriterfilter:SvcUtilFilter.CodeWriterFilter,SvcUtilFilter

(For more information about parameters execute command : crmsvcutil.exe ? )

This will open the UI to connect Organization-

svcUtil2

Connect to your Organization and then wait till your output.cs is ready.

You will be able to find output.cs file in same bin folder once command executed successfully. This file will be having early bound entity classes for your selected entities.

Hope this will help…

Enjoy Ms CRM!!!

Follow on Facebook- FB: MSCRM16Tech


		

Color Picker in MS CRM ?

What is Issue?

How to add Color Picker in MS CRM?
There might be situations where you have to use colors in MS CRM and you wish to have wide range of colors. But in MS CRM there is no field or option available for now.

The Reason-

You have multiple custom controls available in MS CRM right now but there is no option for color picker and there is no way to add your own custom control for now.There is no out-of-box Color picker available in MS CRM.

Solution-

There are 2 solution for the color pickers –

  1. You can use Option set and provide user to select limited options of colors.
  2. You can use Custom web resource with your own libraries or open-source libraries.

The first option is reliable, but not much attractive if user wants some colorful UI and wide range of colors.

Using second option is not supported way but it gives you attractive interfaces.

There is open-source library available for color Picker – spectrum

You can use this library with dynamics CRM as web resources. You can have very nice color picker in MS CRM with these libraries.

ColorPicker

 

Hope this will help…

Enjoy Ms CRM!!!

Calendar and Calendar Rules in MS CRM

What is the Issue?

Calendar is the great feature provided by MS CRM which is used by the scheduling system to define when an appointment or activity is to occur. But when it comes to be used by other entities in case of calculation of dates which will consider the holidays and weekends , it becomes difficult to handle. OOB there is no option to use calendar directly in entities.

The Reason-

Calendar is only entity directly available in MS CRM to be used by developers, You will not be able to access Calendar Rules entity type record which holds the information of free/busy times for a service and for resources or resource groups, such as working, non-working, vacation, and blocked.

 Solution-

As there is no Out-Of-Box option, You need to go with custom code.

First let’s understand the calendar, Holidays Calendar and Calendar Rules-

You will find the calendar under Setting > Service Management >Customer Service Schedule. You can follow the below screens to configure your Business calendar-
Calender1

You can create Calendars as below with work days, work Hours and Holidays details .
This is the main calendar (with type 1) which is used to consider weekend and work hour in activities and appointments.
Calender2

Holiday Schedule has a lookup for another calendar entity record with type 2 i.e. Holiday Scheduler calendar.
Calender3

You have to create this Holiday calendar as below-Calender4Calender5

You can configure multiple holidays here-
Calender6
Calender7

There is Calendar Rule entity record associated with the Calendar entity ( Service Schedule and Holidays Schedule calendar) which holds information inside calendar like week days , Work Hour and Holiday start , holiday end, etc.

Now coming to the solution for our issue-

As we have the option for custom code,

And In case of c# code- we can use entity  “calendar” and “calendarrule” like-
Entity calendar= new Entity(“calendar”);
Entity calendarRule= new Entity(“calendarrule”);
And use OrganizationService object to play around calendar.

In case of javaScript, we can access the information using WebApi like
[organization URI]/api/data/v9.1/calendars
Use WebApi methods GET, POST, PATCH and DELETE operations.

[organization URI]/api/data/v9.1/calendarrules
It is not possible to perform GET, POST, PATCH and DELETE operations with this entity. This can be retrieved along with Calendar WebApi call, as a sub entity record.

You can refer the below code for javaScript to retrieve the Calendar and Holiday Schedule information-

Calender8

 

Hope this will help you to play with calendar.

Enjoy MS CRM!!!