Wednesday, 13 February 2019

Party List Fields in Dynamics 365





















In Dynamics 365, an activity (phonecall, task, email, appointment) can either be associated with a single person or a group of person which represent the Activity Party. An activity can have multiple activity parties.

For Example, an email can either be sent to CRM Contacts or CRM User or Queue. So there must be such type of field available in CRM which can refer to multiple entities as Lookup can only be associated to only single entity. Hence Party List comes into picture.

When you add any Party List type of field on the CRM form, you may notice that these fields look like Lookup fields but may function a little different. For example the Email's From and To fields let you select multiple records of the same or different type.




























  • CRM Activity Party List field is a special type of lookup field which refers to multiple entities. To hold or store these multiple entities references, Microsoft has provided one special type of entity named Activity Party.
  • Activity Party, has one special field called Party Id. which has the capability to store multiple entities references like user, contact, account, lead etc.
  • Hence, if we have to get/set value in Party List Field, we have to interact with Activity Party Party Id field.
  • So, we just have to remember, while getting or setting value in party list fields (to, from cc, bcc, regarding etc). We have to use Activity Party Entity and Party Id field. We can understand it better through code also.

Get value from Party List Fields using C#

public static void Main(string[] args)
{
  // Pass the email record guid
  getPartyList("C4723A9F-592F-E911-A979-000D3AF24324");
}
public static void getPartyList(string emailRecordId)
{

// Retrieve email record
//Here service is your IOrganisation Service Object
Entity email = 
service.Retrieve("email",new Guid(emailRecordId),new ColumnSet("from", "to"));


// get value from partylist - 'FROM' field
EntityCollection from = email.GetAttributeValue<EntityCollection>("from"); if (from != null && from.Entities.Count > 0) { foreach (var item in from.Entities) {
  EntityReference partyId = item.GetAttributeValue<EntityReference>("partyid");

  string addressUsed = item.GetAttributeValue<string>("addressused");

  Console.WriteLine("Email Send From: " + partyId.Name + "," + addressUsed);

  }
 }

Console.WriteLine("------------------------------------------------------------------");

// get value from partylist - 'TO' field
EntityCollection to = email.GetAttributeValue<EntityCollection>("to"); if (to != null && to.Entities.Count > 0) { foreach (var item in to.Entities) { EntityReference partyId = item.GetAttributeValue<EntityReference>("partyid"); string addressUsed = item.GetAttributeValue<string>("addressused"); Console.WriteLine("Email Send To: " + partyId.Name + "," + addressUsed); } } Console.ReadKey();

}


Output


























Set value in Party List Fields using C# (Single Recipient)

public static void Main(string[] args)
{
  // call the function in Main
SetPartyList_SingleRecipient();
}

public static void SetPartyList_SingleRecipient()
{          
  // declare party list entity to set value in FROM field
  Entity from = new Entity("activityparty");
  // declare party list entity to set value in TO field
  Entity to = new Entity("activityparty");
           
  // set value in FROM field
  from["partyid"] = 
new EntityReference("systemuser", new Guid("D72D8D9E-FCEC-4C6B-8340-A2CB9FAA88D5"));

  // set value in TO field
  to["partyid"] = 
new EntityReference("account", new Guid("475B158C-541C-E511-80D3-3863BB347BA8"));

  // declare party list entity to set value in FROM field
  Entity email = new Entity("email");

  // insert value in email FROM field
  email["from"] = new Entity[] { from };
  // insert value in email TO field
  email["to"] = new Entity[] { to };

  //Set regarding object property (i.e. The entity record, which u want this email associated with)
  EntityReference regardingObject = 
new EntityReference("contact", new Guid("49A0E5B9-88DF-E311-B8E5-6C3BE5A8B200"));
  
  email.Attributes.Add("regardingobjectid", regardingObject);

  //Set subject & body properties
  email.Attributes.Add("subject", "Email created from Console for Single recipients");
  email.Attributes.Add("description", "Email created from Console for Single recipients");

  //Create email activity
  //Here service is your IOrganisation Service Object
Guid emailID = service.Create(email); Console.WriteLine("Email created successfully"); Console.Read();
}


Output
























Set value in Party List Fields using C# (Multiple Recipient)

public static void Main(string[] args)
{
  // call the function in Main
SetPartyList_MutipleRecipient();
}

public static void SetPartyList_MutipleRecipient()
{
 // set value in FROM party list field
 Entity from1 = new Entity("activityparty");

 // two accounts inside the TO field
 Entity to1 = new Entity("activityparty");
 Entity to2 = new Entity("activityparty");
 // two contacts inside the TO field
 Entity to3 = new Entity("activityparty");
 Entity to4 = new Entity("activityparty");

 // set value in FROM field
 from1["partyid"] = 
new EntityReference("systemuser", new Guid("D72D8D9E-FCEC-4C6B-8340-A2CB9FAA88D5"));

 // set multiple values in TO field
 to1["partyid"] = 
new EntityReference("account", new Guid("475B158C-541C-E511-80D3-3863BB347BA8"));
 to2["partyid"] = 
new EntityReference("account", new Guid("A8A19CDD-88DF-E311-B8E5-6C3BE5A8B200"));
 to3["partyid"] = 
new EntityReference("contact", new Guid("25A17064-1AE7-E611-80F4-E0071B661F01"));
 to4["partyid"] = 
new EntityReference("contact", new Guid("49A0E5B9-88DF-E311-B8E5-6C3BE5A8B200"));
 Entity email = new Entity("email");

 //Set regarding object property (i.e. The entity record, which u want this email associated with)
 EntityReference regardingObject = 
new EntityReference("contact", new Guid("49A0E5B9-88DF-E311-B8E5-6C3BE5A8B200"));

 email.Attributes.Add("regardingobjectid", regardingObject);

  // Insert value in FROM field
   email["from"] = new Entity[] { from1 };
  // Insert value in TO field
   email["to"] = new Entity[] { to1, to2, to3, to4 };

  //Set subject & body properties
   email.Attributes.Add("subject", "Email created from Console for Multiple recipients");
   email.Attributes.Add("description", "Email created from Console or Multiple recipients");

   //Create email activity
   //Here service is your IOrganisation Service Object
Guid emailID = service.Create(email); Console.WriteLine("Email created successfully"); Console.Read();
}

Output















In the above code,

To get the value from Party List TO and FROM fields:

We are retrieving the value from Party Id field of Activity Party entity, which holds the record’s Guids which was selected in Email’s FROM and TO fields.

To set the value in Party List TO and FROM fields:

We are first passing the value in Party Id field of Activity Party entity and then setting it’s Entity reference to partylist FROM and TO fields.


Note: 

  • For demonstration, I have hard-coded the record Guids. However, in real time you'll have to pick these values dynamically based upon your requirement.
  • For demonstration, I have taken the example of Email Activity Entity and it's To and From party list fields. Same code/logic can also be used for other activities and party list fields.


Thanks for your time. Please do share your valuable feedback. It means a lot for me.

Cheers

Friday, 1 February 2019

Move queue item from one queue to another programmatically in Dynamics 365

This article shows how to add a record from one queue to another.

AddToQueueRequest routeRequest = new AddToQueueRequest
{
        SourceQueueId = queueId.Id,
        Target = new EntityReference(obj.LogicalName, obj.Id),
        DestinationQueueId = userQueueId

};
orgService.Execute(routeRequest);


Sample Code

using Microsoft.Xrm.Sdk;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Crm.Sdk.Messages;
using System.ServiceModel.Description;
using System.Net;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Metadata.Query;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Metadata;

namespace CRMCodeHelper
{
class Program
{
private static IOrganizationService service = null;

static void Main(string[] args)
{       

service = ConnectToCRM();

Guid sourceQueueId = new Guid("9b2296-bacb-e811-a962-000d3ab4998c");

Guid destinationQueueId = new Guid("4f7cd6-54c5-e811-a95d-000d3ab49476");

EntityReference Target = 
new EntityReference("phonecall",new Guid("8d408d-c255-4587-9e34-596d496e6738"));

MoveQueueItem(sourceQueueId, destinationQueueId, Target);

}

public static IOrganizationService ConnectToCRM()
{

IOrganizationService organizationService = null;
try
{

   ClientCredentials clientCredentials = new ClientCredentials();

   clientCredentials.UserName.UserName = "<UserName>";

   clientCredentials.UserName.Password = "<Password>";

   ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

   organizationService = 
new OrganizationServiceProxy(new Uri("<CRM Organisation Service URL>"), null, clientCredentials, null);

   return organizationService;

  }

catch (Exception ex)
{

 Console.WriteLine("Exception caught - " + ex.Message);

 return organizationService;

}

}

public static void MoveQueueItem(Guid SourceQueueGuId, Guid DestinationQueueGuid, EntityReference ItemToMove)
{

 AddToQueueRequest routeRequest = new AddToQueueRequest
 {

    SourceQueueId = SourceQueueGuId,

    Target = ItemToMove,

    DestinationQueueId = DestinationQueueGuid

 };

   service.Execute(routeRequest);

}
}

}

Call Global Custom Action using JavaScript in Dynamics 365

Sometimes there are scenarios you need to create Global Actions where you don't specify an entity in particularly. When you create such global action and if you need to call that action from your JavaScript code or on Button Click. Here is the way to do that.

Example of calling Global Action Without Parameters:

Create a Global Action





























Add Steps and Copy Action Unique Name (My Custom Action)






















JavaScript to call Action

//Execute the created global action using Web API.
function CallGlobalCustomAction() {
    
    //get the current organization name
    var serverURL = Xrm.Page.context.getClientUrl();

    //query to send the request to the global Action 
    var actionName = "new_MyCustomAction"; // Global Action Unique Name

    //Pass the input parameters of action
    var data = {};

    //Create the HttpRequestObject to send WEB API Request 
    var req = new XMLHttpRequest();
    //Post the WEB API Request 
    req.open("POST", serverURL + "/api/data/v8.0/" + actionName, true);
    req.setRequestHeader("Accept", "application/json");
    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    req.setRequestHeader("OData-MaxVersion", "4.0");
    req.setRequestHeader("OData-Version", "4.0");

    req.onreadystatechange = function () {
        if (this.readyState == 4 /* complete */)
        {
            req.onreadystatechange = null;
           
            if (this.status == 200 || this.status == 204)
            {
                alert("Action Executed Successfully...");
               
            }
            else
            {
                var error = JSON.parse(this.response).error;
                alert("Error in Action: "+error.message);
            }
        }
    };
    //Execute request passing the input parameter of the action 
    req.send(window.JSON.stringify(data));
}




Example of calling Global Action with Parameters:























JavaScript to call Action

//Execute the created global action using Web API.
function CallGlobalCustomAction() {
    
    //get the current organization name
    var serverURL = Xrm.Page.context.getClientUrl();

    //query to send the request to the global Action 
    var actionName = "new_MyCustomAction"; // Global Action Unique Name

    //set the current loggedin userid in to _inputParameter of the 
    var InputParameterValue = Xrm.Page.context.getUserId();
 
    //Pass the input parameters of action
    var data = {
    "MyInputParameter": InputParameterValue
    };
//Create the HttpRequestObject to send WEB API Request var req = new XMLHttpRequest(); //Post the WEB API Request req.open("POST", serverURL + "/api/data/v8.0/" + actionName, true); req.setRequestHeader("Accept", "application/json"); req.setRequestHeader("Content-Type", "application/json; charset=utf-8"); req.setRequestHeader("OData-MaxVersion", "4.0"); req.setRequestHeader("OData-Version", "4.0"); req.onreadystatechange = function () { if (this.readyState == 4 /* complete */) { req.onreadystatechange = null; if (this.status == 200 || this.status == 204) { alert("Action Executed Successfully...");

               //You can get the output parameter of the action with name as given below
               result = JSON.parse(this.response);
               alert(result.MyOutputParameter);
} else { var error = JSON.parse(this.response).error; alert("Error in Action: "+error.message); } } }; //Execute request passing the input parameter of the action req.send(window.JSON.stringify(data)); }




Thursday, 31 January 2019

Get Entity Logical Name from its Object Type Code in Dynamics 365

Being a CRM developer, while writing the code, you might need to get the Entity Logical Name from its Object Type Code,

So here is the code to do the same:

public static string geEntityLogicalName(int ObjectTypeCode)
{
            string entityLogicalName = String.Empty;

            MetadataFilterExpression EntityFilter = 
new MetadataFilterExpression(LogicalOperator.And);

            EntityFilter.Conditions.Add(new MetadataConditionExpression
("ObjectTypeCode", MetadataConditionOperator.Equals, ObjectTypeCode));

            MetadataPropertiesExpression mpe = new MetadataPropertiesExpression();

            mpe.AllProperties = false;

            mpe.PropertyNames.Add("ObjectTypeCode");

            EntityQueryExpression entityQueryExpression = new EntityQueryExpression()
            {

                Criteria = EntityFilter,

                Properties = mpe

            };


            RetrieveMetadataChangesResponse initialRequest = 
GetMetadataChanges(entityQueryExpression, null, DeletedMetadataFilters.OptionSet);

            if (initialRequest.EntityMetadata.Count == 1)
            {

                entityLogicalName = initialRequest.EntityMetadata[0].LogicalName;

            }

            return entityLogicalName;

        }


        protected static RetrieveMetadataChangesResponse GetMetadataChanges
(EntityQueryExpression entityQueryExpression, String clientVersionStamp, DeletedMetadataFilters deletedMetadataFilter)
        {

            RetrieveMetadataChangesRequest retrieveMetadataChangesRequest = 
new RetrieveMetadataChangesRequest();
            {

                Query = entityQueryExpression,

                ClientVersionStamp = clientVersionStamp,

                DeletedMetadataFilters = deletedMetadataFilter

            };


            return (RetrieveMetadataChangesResponse)service.Execute(retrieveMetadataChangesRequest);

  }

Dynamics 365 Entity Object Type Code List:

Complete Code:

using Microsoft.Xrm.Sdk;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Crm.Sdk.Messages;
using System.ServiceModel.Description;
using System.Net;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Metadata.Query;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Metadata;


namespace CRMCodeHelper
{
    class Program
    {        
        private static IOrganizationService service = null;
  
        static void Main(string[] args)
        {         
            service = ConnectToCRM();

            string entityLogicalName = geEntityLogicalName(112);

            Console.WriteLine("Entity Logical Name is: " + entityLogicalName);            

            Console.ReadLine();
} public static string geEntityLogicalName(int ObjectTypeCode) { string entityLogicalName = String.Empty; MetadataFilterExpression EntityFilter =
new MetadataFilterExpression(LogicalOperator.And);

            EntityFilter.Conditions.Add(new MetadataConditionExpression
("ObjectTypeCode", MetadataConditionOperator.Equals, ObjectTypeCode));

            MetadataPropertiesExpression mpe = new MetadataPropertiesExpression();

            mpe.AllProperties = false;

            mpe.PropertyNames.Add("ObjectTypeCode");

            EntityQueryExpression entityQueryExpression = new EntityQueryExpression()
            {

                Criteria = EntityFilter,

                Properties = mpe

            };


            RetrieveMetadataChangesResponse initialRequest = 
GetMetadataChanges(entityQueryExpression, null, DeletedMetadataFilters.OptionSet);

            if (initialRequest.EntityMetadata.Count == 1)
            {

                entityLogicalName = initialRequest.EntityMetadata[0].LogicalName;

            }

            return entityLogicalName;

        }


protected static RetrieveMetadataChangesResponse GetMetadataChanges
(EntityQueryExpression entityQueryExpression, String clientVersionStamp, DeletedMetadataFilters deletedMetadataFilter)
{

            RetrieveMetadataChangesRequest retrieveMetadataChangesRequest = 
new RetrieveMetadataChangesRequest()
            {

                Query = entityQueryExpression,

                ClientVersionStamp = clientVersionStamp,

                DeletedMetadataFilters = deletedMetadataFilter

            };


            return (RetrieveMetadataChangesResponse)service.Execute(retrieveMetadataChangesRequest);

        }

        public static IOrganizationService ConnectToCRM()
        {

            IOrganizationService organizationService = null;

            try
            {

                ClientCredentials clientCredentials = new ClientCredentials();

                clientCredentials.UserName.UserName = "<Username>";

                clientCredentials.UserName.Password = "<Password>";

                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

                organizationService = new OrganizationServiceProxy(new Uri("<CRM Organisation Service URL>"),

                    null, clientCredentials, null);

                return organizationService;

            }

            catch (Exception ex)
            {

                Console.WriteLine("Exception caught - " + ex.Message);

                return organizationService;

            }

        }

    }

}


Output:




Thursday, 10 January 2019

Introduction of Azure Function and its Integration with Dynamics 365






What is Azure Function?

We all grew up learning Functions in C#. A Function allows you to encapsulate a piece of code and call it from other parts of your code. You may very soon run into a situation where you need to repeat a piece of code, from multiple places, and this is where functions come in.

In the same way, Azure Function is a function (can be written either directly in Azure or through Visual Studio), which allows you to encapsulate a piece of code on cloud and can call it from any platform.

Technically, Azure Functions is the on-demand execution of functions or small fragments of code based on events. it is a serverless compute service that enables you to run code-on-demand without having to explicitly provision or manage infrastructure. Use Azure Functions to run a script or piece of code in response to a variety of events.




Let's understand it through an example:

Since we are dynamics people and talking in the context of Dynamics CRM, Therefore we understand the Azure Function through one Dynamics CRM requirement.

Let suppose, you have a requirement, where you have to call a web service (given by your client) in order to pass the CRM information to the third party application/system. To implement that, I can only go with the following options in Dynamics CRM

  • Plugins
  • Custom Workflow
  • Custom Action 
  • JavaScript or WEB API.

Being a dynamics developer, you would like to keep the web service calling logic/code at one place instead of writing it repeatedly in Plugin, Custom Workflow, Custom Action and WEB API.

Azure Function is the best way to keep your logic/code at one place on cloud and can call it from anywhere, not only from the CRM but also from outside CRM either using C# Console, Web Applications, Window Applications, JAVA Applications or through other languages like Python, Javascript, PHP, F# Powershell etc. (Supported Languages)

Hence, Azure Function is a piece of code which we can keep it on the cloud and can call it from anywhere (inside and outside CRM) on a particular event to fulfil our requirement.

Why Azure Function?

Someone might have a query that, why I need Azure Function just to keep my logic/code on the cloud? I might also go with CRM Custom Actions as well. Because Custom Action is also provided by Microsoft to reuse the code/logic in CRM. We can keep the logic/code in our Custom Acton and can call it either through Plugin/Custom Workflow or WEB API. Then why Azure Function?

Answer is: 
  • Custom Actions needs to be created in Visual Studio and in CRM both in order to configure its scope(entity or global) and parameters, then only you can call it through either plugin, workflow or javascript.
  • As per my personal experience, In case of any error or issue, debugging of custom action is very complex and not have proper troubleshooting mechanism provided by Microsoft.
  • Tracing of an error log is not possible in Custom Action using ITracingService.
  • Custom Action is only limited to CRM, can't use it through other platforms and languages.
  • Need Visual Studio to write the code.
My intention was not to prove the concept of Custom Actions wrong. It has its own benefits. However, if we talk about the different options in Dynamics CRM to write the Server Side code then we had only following four options available:
  • Plugins
  • Custom Workflows
  • Custom Actions
  • C# External Applications (Web, Console, Window etc).
Those are all great options, but, for many years, they have been the only options available to us. And, yet, they all have limitations. Plugins can’t run on their own. Custom workflow activities have to run as part of the workflows. External applications need a server to run on. There is always a limitation.

Now, we have one more option to extend the Dynamics CRM customization to a new level, which is Azure Functions.

Few more benefits of Azure Functions are:

  • Monitoring and Tracking- We have access to execution log and if we want the result of previous executions, in the options of the function we can find the monitor.

  • Scheduled the Logic - Azure function provide the provision to schedule the logic/code at a defined time interval. For example, in Dynamics CRM, the scheduled workflow has always been a problem? It’s been bugging us since the early days of Dynamics, and there has never been a good solution. There is still no standard/simple solution in Dynamics but stop thinking Dynamics.. think Azure Function.

  • Retry the Logic - Azure function can be retried automatically in case of any error.

  • Reusability -  Code/logic can be called through various places (inside and outside CRM).
  • Support various Languages - Check this for more info.


How to call Azure Function in Dynamics CRM?

Let's take a very simple requirement to understand, how Azure Functions can be called through CRM Plugin:

Create a Task which will store the Azure Function response on create of Contact record.

1. Log in to Azure


Sign in to the Azure portal at https://portal.azure.com with your Azure account.

2. Create a function app

You must have a function app to host the execution of your functions. A function app lets you group functions as a logic unit for easier management, deployment, and sharing of resources.

Select the New button found on the upper left-hand corner of the Azure portal, then select Compute > Function App.


or




3. Use the function app settings as specified in the table below the image.





4, Select Create to provision and deploy the function app.

5. Select the Notification icon in the upper-right corner of the portal and watch for the Deployment succeeded message.




6. Select 'Go to resource' to view your new function app.

7. Click on + New function




8. Create an HTTP triggered function


9. Provide function information as shown below


10.  Update the code and set first name, last name, email parameter


A function is created using a language-specific template for an HTTP triggered function.

Now, you can run the new function by sending an HTTP request.

Update Request body Parameter as below



11. Test the function

In your new function, click </> Get function URL at the top right, select default (Function key), and then click Copy. You'll get the url in below format:https://<functionApp>.azurewebsites.net/api/<function>?code=<key>




















Paste the function URL into your browser's address bar. Add the query string value &firstname=<yourname>&lastname=<lastname>&email=<your email> to the end of this URL and press the Enter key on your keyboard to execute the request. You should see the response returned by the function displayed in the browser.

You can use Postman also in order to test your Azure Function.

Also, you can directly test the response from Azure itself.






12. Trace log of Azure Function

When your function runs, trace information is written to the logs. To see the trace output from the previous execution, return to your function in the portal and click the arrow at the bottom of the screen to expand the Logs.

















13. Write Plugin to call Azure Function

using Microsoft.Xrm.Sdk;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading.Tasks;

namespace DemoPluginToCallAzureFunction
{
    public class Contact
    {
        public string firstname { get; set; }
        public string lastname { get; set; }
        public string email { get; set; }
    }

    public class AzureFunctionCaller : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {

            // Obtain the execution context from the service provider.
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

            ITracingService tracingService =
               (ITracingService)serviceProvider.GetService(typeof(ITracingService));

            // Obtain the organization service reference.
            IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

            try
            {
                // The InputParameters collection contains all the data passed in the message request.
                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
                {
                    // Obtain the target entity from the input parameters.
                    Entity entity = (Entity)context.InputParameters["Target"];
                 
                    using (WebClient client = new WebClient())
                    {
                        var myContact = new Contact();
                        myContact.firstname = entity.Attributes["firstname"].ToString();
                        myContact.lastname = entity.Attributes["lastname"].ToString();
                        myContact.email = entity.Attributes["emailaddress1"].ToString();


                        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Contact));

                        MemoryStream memoryStream = new MemoryStream();

                        serializer.WriteObject(memoryStream, myContact);

                        var jsonObject = Encoding.Default.GetString(memoryStream.ToArray());

                        var webClient = new WebClient();
                        webClient.Headers[HttpRequestHeader.ContentType] = "application/json";

                        // our function key
                        var code = "123W1gzjHaQkJ7Xid19fRPaLCBSxbS0/107645AscDbJ5STVvrz3mjh4A==";

                        // the url for our Azure Function
                        var serviceUrl = "https://mycrmtestfunapp.azurewebsites.net/api/CRM_Contact_Information?code=" + code;

                        // upload the data using Post mehtod
                        string response = webClient.UploadString(serviceUrl, jsonObject);

                        // Create Task with response from Azure function
                        Entity taskObj = new Entity("task");

                        taskObj["subject"] = "Azure Function Called Successfully..";
                        taskObj["description"] = "Azure Response: "+ response;
                        taskObj["regardingobjectid"] = new EntityReference("contact", entity.Id);

                        service.Create(taskObj);
                    }

                }


            }  // try end
            catch (Exception ex) {

                throw new InvalidPluginExecutionException(ex.Message);

}
}
}
}

How to Monitor Azure Function?

Click on Monitor tab for the Function and select the log created for our test run. We can see the values for the parameters in the invocation details section.

Please check the following article:


How Azure Functions Pricing Works?

You only pay when the Azure Function is run. Please check the following article:

https://azure.microsoft.com/en-in/pricing/details/functions/



Supported languages in Azure Functions?

This article explains the levels of support offered for languages that you can use with Azure Functions.

https://docs.microsoft.com/en-us/azure/azure-functions/supported-languages


Caching in Azure Function?

Problem Statement –

Azure Functions are stateless in nature. Therefore even though we can use the standard.Net objects to cache values, they don’t persist if the Azure Function scales out or is idle for some time.

In many cases, Azure Functions are used for doing some integrations with other applications. For example, we may have an integration scenario in which we make calls to OAuth Rest API’s. In these cases, we may need to preserve OAuth2 bearer tokens in Azure Function.

Approach – We have some approaches for doing caching in Azure Functions.

a) Using standard Memory Objects – For example, we can create static objects like the dictionary for caching the values.

However as indicated previously, if the function is idle for some time or scales out, the cached value will be lost.

As a side note, below is the code snippet shows how we can implement assembly caching to save values

// Use the mentioned below statement to include required classes

using System.Runtime.Caching;

// Static object in which we will save the cache

static readonly ObjectCache tokenCache = MemoryCache.Default;

// Retrieving existing value in the cache

CacheItem tokenContents = tokenCache.GetCacheItem(TokenKey);
if (tokenContents == null)
{

// Branch when cache doesn’t exist. This would mean we need to regenerate it.
CacheItemPolicy policy = new CacheItemPolicy();
policy.Priority = CacheItemPriority.Default;

// Setting expiration timing for the cache
policy.AbsoluteExpiration = DateTimeOffset.Now.AddHours(1);
tokenContents = new CacheItem(TokenKey, tokenResponse.access_token);
tokenCache.Set(tokenContents, policy);
}
else
{

 // Branch to retrieve existing value present in the cache
Token = tokenContents.Value.ToString();
}

b) Using Redis Cache – Its managed by Microsoft is highly scalable and provides super fast access to data. Performance wise it can be good but from the pricing perspective, it can cost more than the other options. I'll explain about the Redis Cache in my upcoming article.

Source: https://crmazurecomponents.wordpress.com/2018/08/11/caching-in-azure-functions/


Best Practices of Azure Functions?

Following article provides the guidance to improve the performance and reliability of your serverless function apps.:

https://docs.microsoft.com/en-us/azure/azure-functions/functions-best-practices


Reference:



Thanks a lot for your time reading this article. Your feedback and suggestions are always welcome. In my next article, I'll explain, how Azure Functions can be written through Visual Studio. Till then,
Stay Tuned. 

Cheers 😎


Blogger Widgets