Thursday, January 10, 2019

How to integrate Angular with CRM



WHY CRM?

Today’s consumers are literally bombarded with all sorts of messages and offers that spring out from every corner.
Think about it for a minute, how many times per day do we receive promotional emails from a page you signed up for?
And more importantly, how often do you actually read it!! These days everyone is on social media, on blogs and anyone can comment, read or share.
We cannot go about a one size fits all approach, as these days customers have become more discerning and tech savvy. They are more aware of what they want and the array of options available to them. They demand personalized and diverse means of engaging with products and services.
Most marketers around the world believe that personalization of the web experience is most critical, 74% of respondents claim to get frustrated with websites when content, offers, ads and promotions appear to have nothing to do with their interests and this study results, paint a picture of a more eager consumer base than ever before.
 Not only do consumers get frustrated with irrelevant sites, they are also willing to leave the site completely.
Now, let’s address the elephant in the room, what could this possibly mean for today’s marketers?
This means that the need of the hour is Relevance. Today, we are talking about the rise of a highly individualized marketing approach, which is mainly driven by data and technology.
As a result, the ways marketers do their jobs and fulfill their main duty – to increase interest through a lead nurturing strategy and to multiply customer conversions – have changed.
And it is a CRM system that can help marketers to stay on top of the game.

WHY ANGULAR?

The days of cluttered websites, broken links and unresponsive websites are now a thing of the past. The time has come to embrace the modernization of web development through interactive, responsive and dynamic templates.
At a time when website development was as competitive as finding a needle in a haystack; everybody’s favorite search engine, Google developed Angularjs, an advanced framework created to make the front-end development process simplified.
If we have to get into the nitty-gritty of what makes Angular tick; Angular describes itself as a toolkit for enhancing HTML. It lets you extend HTML with a new vocabulary – in the form of directives – that turn a static HTML page into a dynamic template.
Directives can appear as attributes and tags and they turn static HTML pages into something that lives and breathes.
Angularjs is infused with a rich resource pool which makes it easy for professionals to create websites by writing minimum code. And since the integral parts of app code do not have any directives, it becomes easy for the teams working in parallel to manage them. Code writing mitigations means saving a lot of time and effort.
AngularJs operates on the client side; hence it is compatible with both; web and mobile browsers. It is also versatile, which means we can make front end development without making any backend manipulations.
The two way binding functionality of Angular JS is worth mentioning, as a part of it, any changes that happen in the application have an effect on the user-interface and vice versa. With AngularJs framework, the user actions and module changes happen simultaneously.
Apart from all the above, the hotspot of angularjs is its offer of modularity.  It enables the developers create multiple modules on a single application.  All these modules are either dependent or independent of each other, but one way or another they can be mapped together to work as a full fledged application.

WHY ANGULAR CRM integration?

Building great applications quickly is a key challenge to empower organization. There is something in Angular and Dynamics 365 that makes professional and business love it.
We believe it will be a fine grained mix of a perfect fit with the angular with beautiful look and user experience with number of unique features integrate with Dynamics 365.

How do we handle it? What are the challenges?

The major challenge is to move the angular project output to CRM

Angular developers use TypeScript, which allows developers to find bugs and mistakes earlier in the process. TypeScript also allows developers that are new to a codebase to more quickly get up to speed due to their ability to more quickly see the types of data moving through the application. Angular applications are broken into modules and components, and developers have the ability to import and export subparts of their application as needed. This is a very familiar mental model and also helps developers get up to speed more quickly, and it helps them architect their applications successfully.

Dynamics CRM accepts JavaScript as web resources for it processing.
Believe it or not, our biggest hurdle is debugging the code which is written in type script in CRM

Next challenge is to refer CRM client object modal in angular type script

Last challenge is simple; how do we utilize CRM services in Angular projects.

I am planning to have a series of posts related to this topics by including a POC project.

I believe, you are interested on this topic and could contribute to make the full framework, I really appreciate your subscription and contribution to this project.

We will detail below topics


How do we debug type script from CRM





How do we refer CRM client object from angular application

How do we call CRM service from angular application

How do we move Angular application to CRM

Wednesday, January 27, 2016

Abstracting CRM Providers Using Interfaces







I have created a custom module which can switch to CRM as needed. At present I am using CRM as my Source of Record for custom module. I would like to make sure that custom module, could able to connect to any source of records example sales force, share point portal or any custom application. 

That thought lead me to apply factory pattern for CRM provider


Consider the following sample classes, which allows you to obtain a specific connection object based on the value of a custom enumeration or configuration.

Data Provider class

namespace DataLayer
{
   public abstract class DataProvider
   {
       // singleton reference to the instantiated object
       static DataProvider _provider;
       // constructor
       static DataProvider()
       {
          
           CreateProvider();
       }

       // dynamically create provider
       static void CreateProvider()
       {
           _provider = (DataLayer.DataProvider)Activator.CreateInstance(Type.GetType("<CRMProvider type Name> Ex: DataLayer.CRMProvider can get from config"));
       }
      
       #region Abstract methods
       You can define all your abstract methods here
Ex:   public abstract MasterRecord TestAddMasterRecord(MasterRecord MasterRecord);
       #endregion
   }
}


CRM Provider

namespace DataLayer
{

   
    public class CRMProvider : DataProvider
    {
        const string ProviderType = "CRM";
        readonly OrganizationService _crmService;


        public CRMProvider()
        {
            if( _crmService ==null)
            {
            _crmService = Getservice();
            }
        }

        public OrganizationService Getservice()
        {
            #region Create CRM Connection
            CrmConnectionManagement OConnectionManagement = new CrmConnectionManagement();
            return OConnectionManagement.GetService();
            #endregion
        }
       #region Abstract methods
       Implements Methods of Data Provider
  public override MasterRecord TestAddMasterRecord(MasterRecord MasterRecord)
        {
Implement Method
        }
       #endregion

    }
}


You can have any number of Provider which will talk to your module as source of system.

Configuration

<configuration>
<appSettings>
<!-- This key value maps to one of our enum values. -->
<add key="provider" value=" CRMProvider type Name "/>
</appSettings>
</configuration>

 How to Utilize the Provider?

CRMProvider provider = new CRMProvider();

Provider.TestAddMasterRecord(MasterRecord);



About Connection Management Class 

you can utilize existing class available in CRM SDK 




namespace DataLayer
{
    class CrmConnectionManagement
    {
        #region Private Methods

        /// <summary>
        /// Gets web service connection information from the app.config file.
        /// If there is more than one available, the user is prompted to select
        /// the desired connection configuration by name.
        /// </summary>
        /// <returns>A string containing web service connection configuration information.</returns>
        private static String GetServiceConfiguration()
        {
            // Get available connection strings from app.config.
            int count = ConfigurationManager.ConnectionStrings.Count;

            // Create a filter list of connection strings so that we have a list of valid
            // connection strings for Microsoft Dynamics CRM only.
            List<KeyValuePair<String, String>> filteredConnectionStrings =
                new List<KeyValuePair<String, String>>();

            for (int a = 0; a < count; a++)
            {
                if (isValidConnectionString(ConfigurationManager.ConnectionStrings[a].ConnectionString))
                    filteredConnectionStrings.Add
                        (new KeyValuePair<string, string>
                            (ConfigurationManager.ConnectionStrings[a].Name,
                            ConfigurationManager.ConnectionStrings[a].ConnectionString));
            }

            // No valid connections strings found. Write out and error message.
            if (filteredConnectionStrings.Count == 0)
            {
                throw new Exception("An app.config file containing at least one valid Microsoft Dynamics CRM " +
                   "connection string configuration must exist in the run-time folder.");

            }

            // If one valid connection string is found, use that.
            if (filteredConnectionStrings.Count <= 1)
            {
                return filteredConnectionStrings[0].Value;
            }
            return null;


        }


        /// <summary>
        /// Verifies if a connection string is valid for Microsoft Dynamics CRM.
        /// </summary>
        /// <returns>True for a valid string, otherwise False.</returns>
        private static Boolean isValidConnectionString(String connectionString)
        {
            // At a minimum, a connection string must contain one of these arguments.
            if (connectionString.Contains("Url=") ||
                connectionString.Contains("Server=") ||
                connectionString.Contains("ServiceUri="))
                return true;

            return false;
        }

        #endregion Private Methods

        #region public Methods

        public OrganizationService GetService()
        {
            String connectionString = GetServiceConfiguration();
            Microsoft.Xrm.Client.CrmConnection connection = CrmConnection.Parse(connectionString);
            return new OrganizationService(connection);
        }
        #endregion

    }


}





Thursday, November 5, 2015

url with token parameter



Hi Nice day for you, Today I thought before starting my work Let me pass some information to google search content.

I got lot of help from Google search to do my work easier. Sometime I think myself as selfish not contributing back to the search content. So some bit of information which might help somebody else.

Okay.. Yesterday my boss asked me, we need to send a token while we send mails to customers either using Direct CRM features or third party using extracted list from CRM.

That token should help customer to do some action in CRM without much authentication issues. Like... they can change their phone number by clicking a link. They were able to update their marketing mail preferences with the help of URL and so on...

Indeed there are lot of concerns while we go to security team with the solution. They are asking about, Validity of token, Guest authentication, Defense against reply attacks, Defense against identifier misuse, Defense against Man in middle attack blah blah blah…. :-)


I got confused about the solution as always. Does it have SAML Token, Web token, Identify provider required, Encryption required, Counter required, time stamp required.. Lot of thoughts.

At last some solution which worked for me. may be it has some issues, If you are expert on it, please comment.  That will help me.

So ... Created a Function which will provide me a URL If I pass an ID and KeY. Internally it is using encryption


public string DoEncryptedUrl(string PlainText, string Key)
        {
            String EncryptedString = "";
            if (PlainText == null || PlainText.Length <= 0)
                throw new ArgumentNullException("CipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            byte[] IV = GenerateRandomNumber(16);

            #region Adding Time Stamp
            DateTime epochStart = new DateTime(1970, 01, 01, 0, 0, 0, 0, DateTimeKind.Utc);
            TimeSpan ts = DateTime.UtcNow - epochStart;
            string stamp = Convert.ToUInt64(ts.TotalDays).ToString();
            #endregion

            //Create the token text appending Time Stamp
            string TempText = "text=" + PlainText + "&stamp=" + stamp;

            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = System.Text.ASCIIEncoding.ASCII.GetBytes(Key);
                aesAlg.IV = IV;
                ICryptoTransform Encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                using (MemoryStream msEnrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEnrypt, Encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter srEecrypt = new StreamWriter(csEncrypt))
                        {
                            srEecrypt.Write(TempText);
                        }
                        EncryptedString = Convert.ToBase64String(msEnrypt.ToArray());
                    }
                }

            }

            return "token=" + EncryptedString + "&iv=" + Convert.ToBase64String(IV);


        }




This function will provide Encrypted url token content which can append to the URL while sending email. You can utilize this function anywhere.

Yes, you can attach this function as part of your work flow assembly and utilize the value in email templates in CRM. It can be service utilized by JS. It can be part of ETL program, so that you can process bulk data …..

Now we have to decrypt it.


Here is the method which I used

        public string DoDecryptionUrl(string CipherText, string Key)
        {
            String Originaltext = "";
            if (CipherText == null || CipherText.Length <= 0)
                throw new ArgumentNullException("CipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");

            //Getting Encrypted Token & iv separte
            NameValueCollection QueryString = FillFromString(CipherText);

            if (QueryString["iv"] == null || QueryString["iv"].Length <= 0)
                throw new ArgumentNullException("IV");

            //Reverse URL ezcape characters
            // QueryString["token"] = QueryString["token"].Replace('+', '/');
            byte[] encrypteddata = Convert.FromBase64String(QueryString["token"]);
            byte[] IV = Convert.FromBase64String(QueryString["iv"]);

            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = System.Text.ASCIIEncoding.ASCII.GetBytes(Key);
                //aesAlg.Key = System.Text.ASCIIEncoding.ASCII.GetBytes("Informat");
                aesAlg.IV = IV; ;

                // aesAlg.Padding = PaddingMode.None;
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                using (MemoryStream msDecrypt = new MemoryStream(encrypteddata))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {

                            Originaltext = srDecrypt.ReadToEnd();
                        }
                    }
                }

                //Getting Decrypted Token as text and stamp
                NameValueCollection OriginaltextCollection = FillFromString(Originaltext);

                //Validating Time Stamp. Token will have 3 days validity
                DateTime epochStart = new DateTime(1970, 01, 01, 0, 0, 0, 0, DateTimeKind.Utc);
                TimeSpan ts = DateTime.UtcNow - epochStart;
                if ((Convert.ToUInt64(OriginaltextCollection["stamp"])) - (Convert.ToUInt64(ts.Days)) > 3)
                {
                    throw new TimeoutException("Token Time Out");
                }
                else
                {
                    return OriginaltextCollection["text"];
                }
            }

        }






Oh sorry! I forgot to add an identifier for which entity is encrypted. I think you can manage it. I will update it later. Time to start my regular work:-)

Happy Coding!


Look. Send your friends a note every now and then which can save their time and enjoy a coffee with somebody :-)


They need to know you care about them. Share!