Friday, 27 June 2014

Client Side Best Practices of MS Dynamics CRM


Data Validation:

Validate data based on organization requirement as much as possible in client side. This will reduce server side validation and improper data insertion in Database.
Use form programming for additional validation of data that is unique to your organization. For example, your organization may have specific rules about how telephone numbers should be formatted or a minimum length for the Subject field in a service activity.


Java Script Best Practices:

Avoid including unnecessary JavaScript web resource libraries. Instate of writing multiple JavaScript files try to use one file and put all functions required to the entity. This will reduce HTTP Response time.  Usually scripts are cached in your browser after they are loaded the first time.
Use less script on page on-load. It will increase page load performance.
User 2 Jscript files for one entity one will be related the to page and one is the library functions.

e.g:
/********************************************
Purpose: Contains all the realted functions for current page
Entity : Account
Created on :
Modified On :
Modified By :
********************************************/

// Namespace defination
Org = window. Org || { __namespace: true };
Org.Account = Org.Account || { __namespace: true };

(function () {
    //Define Page Onload fuction
    this.OnLoad = function () {...};
   
    //Define Onsave function
    this.OnSave = function () {...};

    //Define funcation related to only this entity
    this.ValidateField = function (name) { if (!Xrm.Page.getAttribute(name).getValue()) return Xrm.Page.getAttribute(name).getLabel(); };
    this.ClearField = function (name) { Xrm.Page.getAttribute(name).setValue(null); };  
   
    //Define Ribbon Functions
    this.HideRibbon = function () {...};
}).call(Org.Account);

Function will be call like Org.Account.ValidateField(new_name);


Any Reusable Funcations should palced in Liabrary Script file.

/********************************************
Purpose: Contains all the reusable functions
Created on :
Modified On :
Modified By :
********************************************/
// JavaScript liabray version 1.0
Org = window. Org || { __namespace: true };
Org.Constants = Org.Constants || { __namespace: true };
Org.Xrm = Org.Xrm || { __namespace: true };

//Reusable Constants
(function () {
    this.fieldType = { Text: "Text", Date: "Date", LookUp: "LookUp" };
    this.fields = [];
}).call(Ericsson.Constants);

//Reusable Functions
(function () {
    this.ValidateField = function (name) { if (!Xrm.Page.getAttribute(name).getValue()) return Xrm.Page.getAttribute(name).getLabel(); };
    this.ClearField = function (name) { Xrm.Page.getAttribute(name).setValue(null); };
    this.ChangeToRequired = function (name) { Xrm.Page.getAttribute(name).setRequiredLevel("required"); };
}).call(Org.Xrm);

When it required to call
Eg : Org.Xrm.ClearField(new_name);

Form Customization:

Whenever any tab is not used for frequent make them collapse to reduce page on load time. When web resources or IFRAMES are included in sections inside a collapsed tab, they will not be loaded if the tab is collapsed. They will be loaded when the tab is expanded. When the tab state changes, the TabStateChange event occurs.
If any script requires to show hide tab or fields, it good to make the field or tab visibility hidden by default. Use scripts in the OnLoad event to show those form elements you want to display.


Friday, 17 May 2013

Send Birthday Email to Contacts using Custom Workflow in MS CRM 2011

To send birthday emails to contacts using custom workflow follow the steps
1. Create a custom entity Birthday.
     - Add one date time field Next Call to keep tomorrows date in order to start workflow every date recurring.
2. Create a Custom Workflow Birthday Alert
    - It will check birthday contacts for today and create one email record for respected contacts.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

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

namespace Birthday
{
    public class Birthday : CodeActivity
    {
        protected override void Execute(CodeActivityContext context)
        {
            //Tracing service
            ITracingService tracing = context.GetExtension<ITracingService>();

            //workfow context
            IWorkflowContext WorkflowContext = context.GetExtension<IWorkflowContext>();
            IOrganizationServiceFactory serviceFactory = context.GetExtension<IOrganizationServiceFactory>();
            IOrganizationService service = serviceFactory.CreateOrganizationService(WorkflowContext.UserId);

            tracing.Trace("Birthday Workflow started");

            //Query to get todays birthday contacts
            QueryExpression birthdayContactsQuery = new QueryExpression
            {
                EntityName = "contact",
                ColumnSet = new ColumnSet("contactid", "firstname"),
                Criteria = new FilterExpression
                {
                    Conditions =
                        {
                            new ConditionExpression 
                            {
                                AttributeName = "birthdate",
                                Operator = ConditionOperator.Equal,
                                Values = { DateTime.Today }
                            }
                        }
                }
            };

            DataCollection<Entity> birthdayContacts = service.RetrieveMultiple(birthdayContactsQuery).Entities;

            foreach (Entity contact in birthdayContacts)
            {
                //Create email
                Entity email = new Entity("email");

                Entity Fromparty = new Entity("activityparty");
                Fromparty.Attributes.Add("partyid", new EntityReference("systemuser", WorkflowContext.UserId));
                Entity Toparty = new Entity("activityparty");
                Toparty.Attributes.Add("partyid", new EntityReference("contact", contact.Id));

                email["from"] = new Entity[] { Fromparty };
                email["to"] = new Entity[] { Toparty };
                email["directioncode"] = true;
                email["subject"] = "Wish you very Happy Birthday";

                // Create the request
                SendEmailFromTemplateRequest emailUsingTemplateReq = new SendEmailFromTemplateRequest
                {
                    Target = email,
                    TemplateId = new Guid(TemplateID.Get(context).ToString()), //Guid("9CB6EC15-D3C2-E211-B090-00155D07ECE3"),
                    RegardingId = contact.Id,
                    RegardingType = contact.LogicalName
                };

                SendEmailFromTemplateResponse emailUsingTemplateResp = (SendEmailFromTemplateResponse)service.Execute(emailUsingTemplateReq);

                //Update next birthday
                contact["birthdate"] = DateTime.Today.AddYears(+1);
                service.Update(contact);
            }

            tracing.Trace("email send successfully");
        }

        //input parameters
        [Input("Template ID")]
        [RequiredArgument]
        public InArgument<string> TemplateID { get; set; }

        [Input("frequently")]
        [Default("1")]
        public InArgument<string> Frequently { get; set; }
    }
}

- register the assembly.
-create a workflow Send Birthday Mail.
-on update of Next Cell call the workflow.
-Select wait condition (timeout equal Next Call).
-Publish the workflow.

3. Create birthday record. Workflow will start and it will start sending emails.


--Hope it Helps !!!