Tuesday, October 10, 2017

Dynamics CRM Development using Object Oriented Design Techniques

#CompositeDesignPattern
Dynamics CRM development can be much easier and efficient using "Object Oriented Design" techniques. Let me explain.

Suppose the case study of dynamics CRM is such that xyz business is having customers as companies each company has sub branches which is again customers. Customers have people representing contacts for the business.

If I say that customers are accounts then sub branches means self relationship with accounts so there is 1-n  self relation between accounts. Now for representatives of company, we have contacts entity in CRM. so there is 1-n relation between accounts and contacts.

Means
1 - N relation : Accounts -> Accounts
1 - N relation : Accounts -> Contacts

Now suppose I want to get all such information, logic and relationships in terms of object oriented design, what I should do is. Firstly I will identify the objects in this case study.

I have two objects Accounts and Contacts.



So now I will surely and definitely  define classes for these objects. i.e. the pillar of object oriented design.
I have Account class and Contact class. Should I start writing these classes and adding properties for the respective objects? But what if I have properties which are same in both objects. Or I will prefer to make and identify properties similar for both classes and all other classes which can be added later for CRM case studies.

So for the purpose of adding similar properties I will like to define an Abstract class. This class will hold the parent class properties and act as base class to share the properties and methods for all child classes (entities of CRM).


Model: (Objects) 


using Microsoft.Xrm.Sdk;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Account
{
    class Model
    {
    }

    /// <summary>
    /// Abstract Entity Class
    /// </summary>
    public abstract class CRMEntity
    {   
        public Entity Entity;
        public EntityReference EntityReference;
        public string EntityDisplayName;
        public string Href;
        public string CurrentAttributeName;
        //Other Common Properties


        public CRMEntity(Entity entity)
        {
            this.Entity = entity;
            this.EntityReference = new EntityReference(entity.LogicalName, entity.Id);
            this.Href = "https://datainvent-sandbox.crm3.dynamics.com/main.aspx?etn=" + Entity.LogicalName + "&id=" + Entity.Id.ToString() + "&newWindow=true&pagetype=entityrecord";
            //     https://datainvent-sandbox.crm3.dynamics.com/main.aspx?etn=insr_inspectionelement&id=60a3e6da-5584-e711-8125-480fcff44541&newWindow=true&pagetype=entityrecord


        }

        public CRMEntity(Entity entity, string EntityDisplayName) : this(entity)
        {

            SetName(EntityDisplayName);
        }

        public void SetName(string EntityDisplayName)
        {
            this.EntityDisplayName = EntityDisplayName;
            this.Entity.Attributes.Add("EntityName", this.EntityDisplayName);

        }

        public bool IsValidAttribute(string name)
        {
            if (this.Entity.Attributes.Contains(name))
                return true;

            return false;
        }

    }

    public class Account : CRMEntity
    {
        public Account ParentAccount { get; set; }
        public List<Account> SubAccounts = new List<Account>();
        public List<Contact> Contacts = new List<Contact>();

        public Account() : base(new Entity(EntityNames.Account)) { }

        public Account(Entity entity) : base(entity) { }

        public Account(Entity entity, Account ParentAccount) : base(entity) {
            this.ParentAccount = ParentAccount;
        }

        public string Name
        {
            get
            {
                CurrentAttributeName = "name";
                if (this.IsValidAttribute(CurrentAttributeName))
                {
                    return this.Entity.GetAttributeValue<string>(CurrentAttributeName);
                }

                return null;
            }
            set
            {
                CurrentAttributeName = "name";
                this.Entity[CurrentAttributeName] = value;
            }


        }

        public Guid AccountId
        {

            get
            {
                CurrentAttributeName = "accountid";
                if (this.IsValidAttribute(CurrentAttributeName))
                {
                    return this.Entity.GetAttributeValue<Guid>(CurrentAttributeName);
                }

                return Guid.Empty;
            }
            set
            {
                CurrentAttributeName = "accountid";
                this.Entity[CurrentAttributeName] = value;
            }

        }

        public string AccountNo
        {
            get
            {
                CurrentAttributeName = "accountno";
                if (this.IsValidAttribute(CurrentAttributeName))
                {
                    return this.Entity.GetAttributeValue<string>(CurrentAttributeName);
                }

                return null;
            }
            set
            {
                CurrentAttributeName = "accountno";
                this.Entity[CurrentAttributeName] = value;
            }


        }

    }

    public class Contact : CRMEntity
    {
        public Account ParentAccount { get; set; }

        public Contact() : base(new Entity(EntityNames.Account)) { }

        public Contact(Entity entity) : base(entity) { }

        public string FirstName
        {
            get
            {
                CurrentAttributeName = "firstname";
                if (this.IsValidAttribute(CurrentAttributeName))
                {
                    return this.Entity.GetAttributeValue<string>(CurrentAttributeName);
                }

                return null;
            }
            set
            {
                CurrentAttributeName = "firstname";
                this.Entity[CurrentAttributeName] = value;
            }


        }

        public string LastName
        {
            get
            {
                CurrentAttributeName = "lastname";
                if (this.IsValidAttribute(CurrentAttributeName))
                {
                    return this.Entity.GetAttributeValue<string>(CurrentAttributeName);
                }

                return null;
            }
            set
            {
                CurrentAttributeName = "lastname";
                this.Entity[CurrentAttributeName] = value;
            }


        }

        public Guid ContactId
        {

            get
            {
                CurrentAttributeName = "contactid";
                if (this.IsValidAttribute(CurrentAttributeName))
                {
                    return this.Entity.GetAttributeValue<Guid>(CurrentAttributeName);
                }

                return Guid.Empty;
            }
            set
            {
                CurrentAttributeName = "contactid";
                this.Entity[CurrentAttributeName] = value;
            }

        }

        public EntityReference ParentAccountId
        {

            get
            {
                CurrentAttributeName = "parentcustomerid";
                if (this.IsValidAttribute(CurrentAttributeName))
                {
                    return this.Entity.GetAttributeValue<EntityReference>(CurrentAttributeName);
                }

                return null;
            }
            set
            {
                CurrentAttributeName = "parentcustomerid";
                this.Entity[CurrentAttributeName] = value;
            }

        }

    }

    public class AccountHierarchy
    {
        public List<Account> Accounts { get; set; }
        public List<Contact> Contacts { get; set; }

        public AccountHierarchy() {
            Accounts = new List<Account>();
            Contacts = new List<Contact>();
        }
    }


    public class EntityNames
    {
        public static string Account = "account";
        public static string Contact = "contact";
    }

}

Saturday, October 7, 2017

X-Frame-Options = Same Origion

This case is about adding iframe in Dynamics CRM and setting asp.net web form / mvc page to show. One error which can prevent page to load is X-Frame-Options = Same Origion. This occur if there is below line in code

 @Html.AntiForgeryToken()



Also this can occur because off AntiForgeryConfig or similar methods. Usually this is present to not allowed suspicious scripts to run. But anti forgery code add header of x-frame-options and sets value equal to 'same origion'. Which means that no cross domain script is allowed to run. If you have Ajax requests from other servers / domains, then chrome show error of

Refused to display from ..... because of X-Frame-Options = Same Origion

Tuesday, September 26, 2017

Custom Dynamics CRM Integration with SharePoint (Tested on Dynamics 365 Online)


Scenario:
Requirement is that there must be Document type with each document, so that when document is uploaded from crm to sharepoint the document type can be tracked.
One solution can be to create a field (text field / option set) in CRM & SharePoint and mapped so that when document is uploaded the filed can be filled. But this solution was not found after hours of effort and searching for SharePoint.

One solution can be to create folder as per each Document Type in respective record. This will give option to upload document using CRM in respective site location which will represent respective folder in SharePoint.

Thursday, September 21, 2017

Custom XRM Library: Enhance functions

Custom XRM Library to enhance the functionality of xrm functions. This library is a small effort from my side. This includes validations and avoid null reference exceptions in javascript.

I am improving it and planning to add more functions and improvements.

Download

Web API retrieve Specific Account all fields


   var customerid = ""; // Pass account guid here or get from context as per your logic.

    // replacing brackets if found in id

        customerid = customerid.replace("{", "");
        customerid = customerid.replace("}", "");

Sunday, June 25, 2017

CRM 365 Online - Discovery Service

Hi,

Today I was writing code in order to use CRM Discovery Service to retrieve my CRM organizations list for Dynamics 365 Online. To find out Web Application URL  (CRM Application Url), Organization Service Url and Organization data service URL






Casting Error of DiscoveryServiceProxy in CRM 365 Online







Problem Solution:
To solve Discovery Service Proxy casting error on Dynamics 365, I have used Microsoft.Xrm.Tooling.Connector


Below is the solution code.


OrganizationDetailCollection orgDet = Microsoft.Xrm.Tooling.Connector.CrmServiceClient.DiscoverOrganizations(CRMService.DiscoveryUri, null, CRMService.CRMcredentials, null);

Debug.Write(orgDet[0].Endpoints[EndpointType.OrganizationService]);


Explanation:

I tried using Microsoft.Xrm.Sdk.Client.DiscoveryServiceProxy as used to do in previous versions of CRM  (Online / On-Premises). Every thing works fine but when the program reached at line where DiscoveryResponse object is casted to its derived class RetrieveOrganizationsResponse, program throw exception as shown.




Friday, February 17, 2017

Web API Retrieve Single Record

Today I am showing how to select an entity record by passing Guid and get back desired fields.
I am running this code on 'Contact' entity and retrieving two fields. I have to remove starting and ending brackets as Web API is not accepting while processing Guids
I am using below javascript code in webresource. For application outside CRM in separate application, u have to first authenticate using Azure / AD depending upon deployment (Online / On-Premises). Refer to this link for this feature.


Code Start:


function MySelectUsingWebAPI() {



var id = Xrm.Page.data.entity.getId();



             id = id.replace("{", "");

            id = id.replace("}", "");



Asp.Net MVC (5) - Exception Filter - HandleError

Applicable on Asp.Net MVC5 HandleError Filter This belongs to Exception Filters category (Authentication Filter, Authoriz...