CRM Ramblingshttps://ansrikanth.com
My experiences with CRM, USD and FamilyWed, 23 May 2018 09:44:45 +0000enhourly1http://wordpress.com/https://secure.gravatar.com/blavatar/41ad9e87bfec594e3ece9c5b205ed26c?s=96&d=https%3A%2F%2Fs0.wp.com%2Fi%2Fbuttonw-com.pngCRM Ramblingshttps://ansrikanth.com
Play safe – Use SafeDispatcher – Stop USD Crashhttps://ansrikanth.com/2018/03/27/play-safe-use-safedispatcher-stop-usd-crash/
https://ansrikanth.com/2018/03/27/play-safe-use-safedispatcher-stop-usd-crash/#respondTue, 27 Mar 2018 08:48:27 +0000http://ansrikanth.com/?p=2036One of the better components that have been released as part of the USD 2.2.1 is ‘SafeDispatcher’. All these days, I hadn’t really given much care or thought to it, but now, after seeing the impact of it practically, I understand how important this component is for all custom hosted control developments. Hence, this blog post.

Note: This blog post is entirely technical and one needs to have some basic understanding of WPF and Custom control development in USD to effectively indulge with it. If you don’t fall in this category, this post might become a bit tedious for you.

Let’s get to know about Dispatcher first. In layman terms, you can consider this as UI Thread. The dispatcher will queue all your code commands into UI thread and will get executed one by one. Until and unless you explicitly mention that this piece of code should run under a separate thread (using Task/Background Worker, etc.), all your code runs under Dispatcher thread by default.

The problem with this Dispatcher/UI thread is that if an unexpected exception occurs in the code which isn’t handled, there is a high chance that your entire application will shut down with a Fatal error. Note that this is the behavior of WPF, not the USD.

So, in case of USD – if one of your custom controls has a problem, imagine how awkward it would be if it crashes the entire USD. How difficult would it be for the agents to start over the USD and go back to the session where they had been working before it crashed? That’s where the SafeDispatcher comes into the picture.

As the name says, it is a ‘Safe’ Dispatcher which can handle all the unhandled exceptions and stops propagating the error further, thereby preventing the USD to crash. In addition to that, it gives a user-friendly message along with full stack trace details for the developers to investigate further.

Here is a quick demo I have created, which I believe will give you a better insight into the topic and will be quick to understand too.

For the sake of this demo, I have created a Global Custom Hosted control. It has 2 buttons: a) Dispatcher, b) Safe Dispatcher. I wrote a couple of methods which throw a Null reference exception, however, one of them is wrapped with Dispatcher, while the other with Safe Dispatcher. Here are some of the screenshots of the code & UI.

Safe Dispatcher UI

Dispatcher.Invoke method

SafeDispatcher.Invoke() method

Now, if I run the application and click on the ‘Dispatcher’ button, you will see that USD has crashed with one big and ugly error message, as shown below:As you can see, there is nothing much in the code. In the first bits, it is a Null object and using GetType() method on Null objects results in Null Reference Exception. This is on UI Thread. In the second piece of code, it is exactly the same, except for the fact that it is SafeDispatcher thread.

Unhanded Exception crashing USD

On the other hand, if you click on ‘Safe Dispatcher’ button, SafeDispatcher component will handle it and will display a nice user-friendly message. Moreover, it will not crash your USD. Here is what the message looks like:

Exception Handled by SafeDispatcher

I hope this demo helps you understand the importance of this SafeDispatcher component in your code.

So, Developers, please, please make sure that you use SafeDispatcher in all places, wherever you are dealing with UI components, and make USD a good application to work with.

All the very best, Happy coding!!

]]>https://ansrikanth.com/2018/03/27/play-safe-use-safedispatcher-stop-usd-crash/feed/0Dispatcher Vs SafeDispatcheransrikanthSafe Dispatcher Vs DispatcherDispatcher.InvokeSafeDispatcher.InvokeUSD CrashException Handled by SafeDispatcherUnsaved CRM changes – Visual representation in USDhttps://ansrikanth.com/2018/02/12/unsaved-crm-changes-visual-representation-in-usd/
https://ansrikanth.com/2018/02/12/unsaved-crm-changes-visual-representation-in-usd/#respondSun, 11 Feb 2018 18:38:44 +0000http://ansrikanth.com/?p=2029The other day, when I’m in discussion with the #USDGuru – @ParkhurstNeil; He showed me his interesting approach to use these emoji icons to display on tabs. He mentioned something similar to this over here. That strikes me the thought – why can’t we use this as a Visual representation for Unsaved CRM Tab? And here you go – on the implementation steps.

GOAL: Display a start (), whenever a Contact has been edited, unsaved and shifted to another tab – that represents the content in the Contact tab is not yet Saved.

NOTE:

– this is just an emoji I used for reference purpose. No hard feelings, you can choose any emoji of your choice. Just ask google

Chosen Contact tab for simplicity to write the post. You can use the same mechanism for any other CRM tab and for that matter for any other standard web application if they have a way of notifying/checking unsaved content.

This is just one simplest way of implementing this scenario. There are a lot of other possible & creative ways still exist with their own pros & cons. No need to stick to this implementation only.

STEPS: Don’t want to waste much time, let’s look at the steps involved

a) An action call to check form is dirty, if so – populate context sensitive variable with our emoji –

Nothing fancy, Checking if the entity is Dirty, If so, Set Emoji Icon, if not make the icon as empty. The next line of code is however interesting – It says USD to call an action named “CopytoContext” available on “CRM Global Manager” with data as “ContactDirty=<<Icon>>”. This is how we normally pass notifications to USD from Client side scripting.

Condition

CRMGlobalManager.IsAppLoaded(“contact”)===true

This condition ensures that the action call fires only if the contact page is loaded in UI.

Action call to check Unsaved Changes in Contact

b) Attach action call to the event. Simply navigate to Unified Service Desk >> Events >> Search for “SelectedAppChanged” (Create one under panel layout, if you don’t find it in your configurations). Add the above action call to this event.

c) Modify the display name of Contact. Navigate to Unified Service Desk >> Hosted Controls >> Contact. Change the existing display name from [[contact.fullname]]-[[Contact.address1_city]] (if you are using OOB configurations) to [[contact.fullname]]-[[Contact.address1_city]] [[$Context.ContactDirty]] .

Contact Hosted control with Context variable to represent unsaved changes

That’s it. Close and Re-open your USD, Modify some content in Contact, Shift focus to a different tab… voila …

POST UPDATE: One of my friends from Microsoft suggested to use Minutes update instead of Seconds as Updating UI via actions for every seconds might cause some performance issues. Henceforth, it is suggested to use this approach only Minute wise update. Please drop a comment incase of any doubts.

First of All – Happy new year to all readers. 2017 has been a fantastic year to me – started my blog, got a new role (with my old buddies) in one of my fav companies and most importantly, Adhi, my cutie pie filled lights with his smiles in our life. I wish the colors continue in 2018 as well for me and to all of you as well:)

Coming to the actual topic of the day – “Display a Timer that shows the active time in a Tab”. One of the most common requirements I see in general is, how much time my agent is working on a case. It may not be really possible to calculate 100% accurate time, but If we consider – “the amount of time he was actively looking into the case itself is the working time”, then this solution would definitely work for you.

Note: This is one simple implementation for this problem, there might be a lot of other ways. Also, for the demo purpose, The post implements the timer on Debugger tab instead of case tab, It’s your duty now to implement it for Case tab :). Remember – “Practice makes perfect”

One last word before jumping into the actual solution, this solution takes the “idea” from a post that has been already implemented by @Neil in this ping-pong post. You might be interested to take a look at it once for some basic understanding on action calls/events etc.

Here are the steps at a glance.

1. Create action call to start/stop timer

2. Create action call to trigger ‘seconds counter’ after one second using ExecuteTimeOut action

Checking if context has debuggertime replacement param, If there increment by 1, If not make it as 1. This is basically to count the number of seconds you are in the debugger tab.
The second line – debuggertimeinHr is just to display the seconds into hh:mm:ss with a simple hack provided over here.

Condition

“[[$context.StopTimer]+]”==”0”

Make sure the StopTimer flag is set to 0 (false).

Step#4: Join both the action calls – AC2 (Action call 2 created in step#2) should have AC3 (Action call 3 created in Step#3) and then AC3 should have AC2 as sub action call. In that way, Whenever AC2 triggers, it waits for 1 sec and calls AC3 => Which then simply increments my counter in context and calls AC2 again. The loop will continue till the time my condition (StopTimer==0) fails on AC3. Here is a quick diagram that might help in understanding this cycle.

Let’s go and add as sub action call to one another. This is how my sub action calls are looking like.

Now that our action calls are ready to use, Let’s go to the final step.

Step#5: Attach action calls to event SelectedAppChanged – an event which tells what is the active tab whenever the tab changed. More info about this event is given by Neil in this post.

That’s it. We are all most done. The leftover part is, displaying the timer. I have modified my Debugger control’s display name as shown below to cater a time display. DONE !! Close & Re-open your USD, Start debugger – Shift focus to Debugger and see.

The final outcome should look like the one on this post title :). Enjoy !!

]]>https://ansrikanth.com/2018/01/07/active-time-in-a-tab-display-timer/feed/0Timer Display to show active timeansrikanthAdding Subsection callAdding Subsection callClear replacement parameter when field is Clearedhttps://ansrikanth.com/2017/11/15/clear-replacement-parameter-when-field-is-cleared/
https://ansrikanth.com/2017/11/15/clear-replacement-parameter-when-field-is-cleared/#respondWed, 15 Nov 2017 11:38:43 +0000http://ansrikanth.com/?p=1982One of the issues what I have observed in the last couple of versions of USD is, It’s inability in refreshing the replacement parameters if the field value is removed.

For eg: I have removed a phone number and saved the form, you will still see the old value in replacement parameters of your entity. It works great if you add/modify a field value though. This causes severe issues if we have used these replacement parameters in any of the conditions.

Here is a quick and simple solution to the problem.

I’m considering Account form and telephone1 field for this demo (Extend it further as per your need).

Let me take a quick moment to see what we are doing here – We are attaching a function to Onsave, which will check for telephone field value and fires a UII action “ScanForDataParemeters” on Account entity if the value is empty. Watch carefully the URL I’m opening http://uii/account/ScanForDataParameters.

The account in the URL is not really the entity logical name rather it should be the Hosted Control name. (for ex: If my account hosted control name is “Session App Account” then the url would be “http://uii/session app account/ScanForDataParameters”)

Attach the action call to “BrowserDocumentComplete” event of the Account hosted control and you are all good to test.

Reopen your USD (if you already opened it), Open an Account and remove the Telephone field value and Save the form. Your replacement parameters should not contain telephone1 field as shown below…

Before

After

Hope you got what you are looking for, Let me know if it is not (via comments) :). All the best, happy coding !!

]]>https://ansrikanth.com/2017/11/15/clear-replacement-parameter-when-field-is-cleared/feed/0Clear replacement parameter when field is ClearedansrikanthReplacement Parameter value before Clearing the valueReplacement paramterAsynchronous CRUD operations in USD using CRM V9 updates.https://ansrikanth.com/2017/11/04/asynchronous-crud-operations-in-usd-using-crm-v9-updates/
https://ansrikanth.com/2017/11/04/asynchronous-crud-operations-in-usd-using-crm-v9-updates/#respondSat, 04 Nov 2017 10:02:28 +0000http://ansrikanth.com/?p=1973It’s been quite a long time by posting a new blog post, bit occupied with our Jr. all these days ..

I would like to start with thealmost new version of USD 3.0 in my come back blog. There are quite a good amount of features present in the new version and 1 particular new feature I was excited about when it is announced is CreateEntity in an Asynchronous way. I don’t want to blog it again as the USD guru @Neil already documented here.

Though I was excited so much when I first read about this feature but it didn’t take much time for me to realize that #INeedMore

a) It’s only CreateEntity is async. In a tweet, @Sid is kind enough to confirm that this is a last moment addition and we can expect other CRUD ops as well in the async mode in next versions. (Excited again to see the new features in to play )

b) No way to identify the exceptions – By any reason if the CreateEntity(async) failed, There is no way that we will come to know about it. Trust me, this going to be a big problem in real production env.

c) Have to wait for the result (using special actions like WaitFoData) if the result is required to process further actions. Somehow, I’m not so comfortable with such kind of waiting conditions.

d) In CreateEntity, It always confuses me and even took a long time to identify on how to pass values for special fields like Money, decimal/double etc.

So, I was on a hunt for a better solution and CRM V9 (the so-called July Release), gave me some pretty good points to solve these problems by using the new Clientside scripting namespace Xrm.WebApi.

Let me quickly jump into action and show you all how can we leverage this new Xrm.WebApi in conjunction with USD and solve the above-mentioned problems.

Step#1: I need a CRM page which is always available for me to use the RunXrmCommand action. The safest I can think of is, SystemUser page which in most cases will not have any additional javascript and I will be anyways loading it in the hiddenpanel, no one knows about it. Here is my hosted control configuration for SystemUser.

Field Name

Field Value

Name

Some meaningful name, Mine is – Global SystemUser CRMPage (Hidden)

Unified Service Desk Component Type

CRM Page

Application is Global

True

Display Group

HiddenPanel

Application is Dynamic

No

Leave all the other configs with default values.

Step#2: Create an action call to load this with logged in user when USD loads.

Field Name

Field Value

Name

Some meaningful name, Mine is – Navigate to System User record

Hosted Control

Control created in the previous step (ie. Global SystemUser CRMPage (Hidden))

Notice the usage of [[systemuser.systemuserid]g] replacement parameter in Data. Now that we have the action call, Attach it to DesktopReady event so that the navigation occurs when the USD is ready to use. Here is how my DesktopReady event looks like.

Step#3: Now we have the framework ready, All we have to do is firing up required CRUD actions asynchronously. Let’s take a scenario where we want to create a phone call record asynchronously whenever a session is started and open it after it is created. Let’s go ahead and create a new Action call which fires Xrm.WebApi command.

No need to be panic with a big “data” field. If we evaluate line by line, All we are doing is creating the data JSON object and passing it to Xrm.WebApi.crateRecord method. On Success we are firing PhoneCallCreated event with ID as parameter and on Failure we are firing PhoneCallCreationFailed event with error message as parameter.

Attach the action call to NewSession event and create the PhoneCallCreated and PhoneCallCreationFailed events on your SystemUser hosted control.

That’s it – you are all set to restart your USD and test. The phone call will get created asynchronously and eventually fires the PhoneCallCreated event where you can simply use open_Crm_page to open the phone call entity if you want. This is how my new phone call got created and opened when I start a new session.

I can see a lot of potential advantages to this approach apart from covering the above-mentioned issues for ex: creating parent and child records at a time, calling an action, executing as an Admin user etc.

Hope it helps you all, Bye for now

]]>https://ansrikanth.com/2017/11/04/asynchronous-crud-operations-in-usd-using-crm-v9-updates/feed/0Asynchronous CRUD Operations in USDansrikanthUSD – Enhanced Forms, Views etc.https://ansrikanth.com/2017/07/02/usd-enhanced-forms-views-etc/
https://ansrikanth.com/2017/07/02/usd-enhanced-forms-views-etc/#commentsSun, 02 Jul 2017 17:14:45 +0000http://ansrikanth.com/2017/07/02/usd-enhanced-forms-views-etc/Microsoft Dynamics 365 and Unified Service Desk: Microsoft’s Unified Service Desk (USD) is a great product but I do often find I like to enhance the views and forms for editing my USD configuration. In this post I provide a link to a managed solution designed to give an improved experience when editing hosted…]]>

I would say one of the must solution for USD, quick n easy to use forms, views n many more.

Microsoft’s Unified Service Desk (USD) is a great product but I do often find I like to enhance the views and forms for editing my USD configuration. In this post I provide a link to a managed solution designed to give an improved experience when editing hosted controls, actions, toolbars etc.

My USD solution is pretty big! Meaning I often find benefit in these improvements, as they help me navigate my solution and make changes quicker. Below you will find a link to the solution I’ve created to give me that enhanced navigation.

This is a managed solution, meaning you can import it, try it and remove if you’d like to return to the out of the box navigation.

To install it, first ensure you have USD installed and then simply import.

]]>https://ansrikanth.com/2017/07/02/usd-enhanced-forms-views-etc/feed/1Featured Image -- 1966ansrikanthSessions history – Capture Active & Total time of Session in USDhttps://ansrikanth.com/2017/06/12/sessions-history-capture-active-total-time-of-session-in-usd/
https://ansrikanth.com/2017/06/12/sessions-history-capture-active-total-time-of-session-in-usd/#respondMon, 12 Jun 2017 05:57:30 +0000http://ansrikanth.com/?p=1936One of the most common business scenario while implementing USD in contact centers is to know the Total time the agent spent in a session and the time actively he/she worked on the session. This can be very good information for all those managers out there to understand the pattern of calls, time taking to deal with customers, ‘extra’ work of agent post session etc.

Though one of my previous posts tells how to create “a” record in CRM from USD, this one involves one interesting Microsoft’s pre-build (careful, I didn’t say OOB ) Timer control. This control has the ability to record the total time the session is opened and the total time that the agent spent on this session (Hoping, you already know that USD gives the flexibility to an agent to open multiple sessions at a time and to work with multiple customers at a time).

So, How do you get the Timer control? Simple -Install USD with basic configurations. It has 2 hidden actions

GetSessionSeconds – Returns the number of seconds that the agent kept open the session

GetSessionUsageInSeconds – Returns the number of seconds that the agent is actively in the session (ie. Not switched to a different session)

Why I said hidden actions is, they will not come to you automatically when you install the USD for some reasons known only to Microsoft :). Not a big deal – Just go and create these actions for the Timer hosted control.

Okay, Theory done – Let’s get into action.

Create Actions for the Timer hosted control

NOTE: This is step is only required if you don’t see the mentioned actions in the Timer hosted control.

4. Repeat the same for GetSessionUsageInSeconds. This is how your timer control actions would look like at the end of this step.

Session Timer Actions

Create an entity to hold the Session history records

5. This is plain CRM process. Go ahead and create an entity with a meaningful name and couple of Integer fields to hold the session time & active time. Here is how my entity looks like

Session History entity

Create Action calls

6. The first action call we are going to create is to get the total session time. Navigate to Settings -> Unified Service desk -> Action calls – > Create new Action call

7. Create an action call with the following information

Field Name

Field Value

Name

Get Session total time (or any other meaningful name if you want)

Order

10

Hosted Control

Timer

Action

GetSessionSeconds

8. Create next action for getting active session time as well with the following information

Field Name

Field Value

Name

Get Session active time (or any other meaningful name if you want)

Order

20

Hosted Control

Timer

Action

GetSessionUsageInSeconds

9. Now that we have created the action calls required to get the data, we will go ahead and use this data to create a new record. Create a new action call to create a new session history record with the following information

Field Name

Field Value

Name

Create Session timer record (or any other meaningful name if you want)

a) Make sure you are changing the entity name and other field names in the Data parameter according to your custom entity name & fields

b) Notice the use of $Return replacement parameters to get the session time & actual time, Any action call that returns output – can be captured from $return replacement parameters.

c) I’m converting the time in minutes by dividing the actual value with 60 and using Math.round to round it. I don’t think you would like to see this information in seconds directly, but it is up to you to convert or not to into minutes

d) To get the Session end time I’m using Javascript’s new Date() method and so to evaluate Javascript values we are using $Expression. You can also see the same in Minute’s conversion as well.

All done, Last step – Wire up the Action calls and Events.

10. The only place that we can get the total session time & active session time is when the user clicks on “Close” button on Session. And the event that fires at that time is “SessionCloseRequested”. So, let’s add all these action calls in the session close requested event as shown below.

image003SessionCloseRequested Event

That’s it, We are done with the configurations part of it. Let’s just test it by opening USD freshly. Start a couple of sessions and wait for few minutes, just play with both the sessions by keeping one active for some time and the other one active for some time. Close the sessions one by on and you should see the result something like shown below.

Hylaa… We just finished one another common business scenario in USD implementations – with absolute 0% coding, which many of my friends out there love :), Hope you also .. !!

]]>https://ansrikanth.com/2017/06/12/sessions-history-capture-active-total-time-of-session-in-usd/feed/0Session HistoryansrikanthSession Timer Actions - GetSessionSeconds, GetSessionUsageInSecondsSession History entitySessionCloseRequested EventTwo way communication between CRM and Azure Service bushttps://ansrikanth.com/2017/04/17/two-way-communication-between-crm-and-azure-service-bus/
https://ansrikanth.com/2017/04/17/two-way-communication-between-crm-and-azure-service-bus/#commentsMon, 17 Apr 2017 09:54:41 +0000http://ansrikanth.com/?p=1844This is the next level of my previous post on Azure service bus integration with CRM. If you haven’t gone through it already, I would highly recommend you to go through it first over here as whatever we are going to do here in this post is kind of an extension to my previous one.

So, in the last post, we saw how we can pass the CRM entity information to ASB (Azure Service Bus) whenever it got created/updated/any other plugin actions happened. And you must have noticed by now that it would be an asynchronous job for us, meaning CRM would be in ‘fire and forget’ mode. All it knows is it has dropped a ‘Message’ in a Queue, it doesn’t know when it got picked up and when it got processed and who picked it up etc. In some cases this might be the exact behavior we are looking for but not in all cases. There might be a scenario where we need information immediately from the service bus, for ex: A quote engine which can calculate the quote value based on a lot of considerations; we can’t really use fire and forget mechanism in such scenarios. That is where the two-way communication between CRM and ASB is helpful. We will see how we will establish a communication in this post.

W/o any further delay lets jump into actions.

Azure Configurations

1. Hoping you have active azure subscription (or at least the trail version which we have created in the previous post), Navigate into your azure portal

2. This time, we are not dependent on a Queue rather we will be using a Virtual path which can be used by the Quote engine and CRM will keep sending messages to this virtual path.

Btw, I’m considering the above mentioned scenario to demo the post

3. From the All Resources menu item, Open the Service bus which we created in the last post. In my case, it is “MyServiceBusForBlog”. (This is why I have asked to follow the previous post )

4. Click on Shared Access Policies under Settings. You should be able to see in the resultant blade a Master access key in policies list. This is the main key with which anyone can control the azure service bus programmatically. So, Keep it safe :). Click on Add button to create a new Shared access Policy.

Shared access Policies in ASB

5. Give a meaningful name (I’ve chosen ReadAndWriteAccessPolicy) for the policy and give ‘Send’ and ‘Listen’ access as shown below and click Create.

6. The blade will close automatically and in few seconds you should be able to see a new Policy got created for this ASB.

7. If you can click on the policy, you should be able to see a couple of Keys (primary key and secondary key) and connections strings associated with these keys. Keep a note of these, we will be using them in the subsequent steps.

Console Application (Quote Engine) to host the Azure Service

8. Now that we have completed required ASB configuration, lets quickly create a console application which will connect to the azure and hosts/listens to a virtual path in our ASB. Create a console application and add following NuGet References (self-explanatory, Note: IdentityModel reference will automatically come if you add SDK assemblies).

9. Now, We have to use ITwoWayServiceEndpointPlugininterface to establish a 2-way communication with CRM. FYI, this is part of SDK Libraries. Create a new class file with name “QuoteEngineListener” and implement the interface as shown below.

public class QuoteEngine : ITwoWayServiceEndpointPlugin
{
public string Execute(RemoteExecutionContext executionContext)
{
/// This Execute method will execute automatically whenever a message has been passed
/// to the service bus.
/// In realworld scenarios this would become a backend worker role and will call the
/// third party services to get the details.
/// We can use the executionContext Object to get the details of the CRM object
var entityName = executionContext.PrimaryEntityName;
WriteLine($"Received message for entity {entityName} with Id {executionContext.PrimaryEntityId}");
WriteLine("Generating quote value....");
if (entityName != "quote")
return "0";
var quoteValue = new Random().Next(1000, 10000);
WriteLine($"Genertated quote value as {quoteValue}");
return quoteValue.ToString();
}
}

Notice the Execute method which returns a string value. This would be the return value that we will be catching in our plugin (explained further below). The Execute method will automatically trigger whenever there is a message pumped to ASB.

And the RemoteExecutionContext is a wrapper class on top of the regular PluginExecutionContext – ie. You should be able to get everything what your plugin execution context contains (like Target entity, Pre & Post Images, shared variables etc etc).

In my code above, I have shown how to get the primary entity name as an example. The method will return a random number as my QuoteValue. Keep in mind it should be a string output only. You have to serialize your complex objects if required.

10. Now under the main method, we will be hosting it as a service inside the azure. Here is how my Main method looks like with detailed explanation.

static void Main(string[] args)
{
try
{
// The access policy we created in previous steps and the Primary key
string sharedAccessKeyName = "ReadAndWriteAccessPolicy";
string sharedAccessKey = @"VRyr0+Msdv0HgoWNSnBZyNxtAZw/Uq55RSPTy96FDOM=";
// This is the standard Azure service bus end point
// MyPath at the end of the URL is the virtual path which is the entry point for the messages
// https://&lt;&lt;ServiceBusName&gt;&gt;.servicebus.windows.net/&lt;&lt;PathName&gt;&gt;
string serviceBusEndpoint = "https://myservicebusforblog.servicebus.windows.net/MyPath";
// QuoteEngine is the class which is inherited from ITwoWayServiceEndpointPlugin
var serviceHost = new ServiceHost(typeof(QuoteEngine));
// Generate the token provider for ASB using Polilcy name and Primary key
var tokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(sharedAccessKeyName, sharedAccessKey);
var transportClient = new TransportClientEndpointBehavior(tokenProvider);
// Add WS2007HttpRelayBinding type end point
serviceHost.AddServiceEndpoint(typeof(ITwoWayServiceEndpointPlugin), new WS2007HttpRelayBinding(), serviceBusEndpoint)
.Behaviors.Add(transportClient);
// Start the service
serviceHost.Open();
Console.WriteLine("listening .. ");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
throw;
}
}
}

The code is pretty much self-explanatory. Let’s have a quick walk through. The first 2 lines are the Shared access policy and primary key we got in step #7. The service bus endpoint is a combination of Service bus name and the virtual path where the service will keep listening for messages. This is how the end point looks like https://<>.servicebus.windows.net/<>

After that, we will be hosting the service with WS2007HttpRelayBidingand start the service.

Make sure to update your relavent Primary key name and policy name and the service bus name in the above code.

11. That’s it, we are done with the hosting part of it. Start the console application and leave it running.

Note: It is mandatory for the service to keep open and in listening state.

Register the Service Endpoint

12. Now, Open the Plugin registration tool and connect to your organization.

13. Click Ctrl+E to register the service point and provide the connection string which we got in Step#7 (For more clear steps on this, refer my previous post). This is how the endpoint registration window should look like https://<&gt;.servicebus.windows.net/<>.

14. Now following steps are crucial and I would suggest to follow them in the same order. If you missed the order at any stage and feel like you messed it up, I would recommend to start again from Step #13.

a. Change Designation Type to TwoWay

b. Change the NameSpace address from sb:// to https://

c. Add the “MyPath” virtual path to the end of the Namespace. End of the step your NameSpace would be the one which we have used in the Console Application’s “serviceBusEndpoint”.

d. Mention the Path as “MyPath”. This how the window should look like at the end of this step

15. Hit save, will take a couple of seconds to create the end point. Once after creating the end point, Click on the properties window and make a note of the Endpoint Id as shown below.

Service endpoint Id

Create a New Plugin project to send the information to ASB

16. Create a new Plugin project (basically a class library project) and do the regular stuff (like adding required reference libraries, IPlugin etc), hoping everyone is well aware of how to create a plugin, I’m not going to stress on this area.

17. Add a constructor, which can accept unsecure config as shown below. Note: My Plugin project name and class name is AzureTwowayCommunication

// Class level global variable to hold the Service end point ID.
private Guid serviceEndPointId;
///
&lt;summary&gt;
/// Standard Plugin Constructor, accepts Unsecure and secure configurations.
/// &lt;/summary&gt;
/// &lt;param name="unsecureConfig"&gt;&lt;/param&gt;
/// &lt;param name="secureConfig"&gt;&lt;/param&gt;
public AzureTwowayCommunication(string unsecureConfig = "", string secureConfig = "")
{
// for the sake of simplicity, I'm using unsecure conifiguration of plugins
// to get the service end point id.
// you might want to use any other "configurable" mechanism to store this id.
if (string.IsNullOrEmpty(unsecureConfig))
throw new InvalidPluginExecutionException("Please provide Service Endpoint ID in unsecure configurations");
if (!Guid.TryParse(unsecureConfig, out serviceEndPointId))
throw new InvalidPluginExecutionException("Please provide Service Endpoint ID in unsecure configurations");
}

Again self-explanatory constructor; nothing fancy. Accepting unsecure and secure configurations. So, in the unsecure configurations, we are going to pass the entity reference of the service endpoint which we created in previous steps. However, it is up to you how you will get this entity reference id. For the sake of simplicity, I have placed it in the unsecure configurations.

So, in the unsecure configurations we are going to pass the entity reference of the service end point which we created in previous steps. However, it is up to you how you will get this entity reference id. For the sake of simplicity I have placed it in the unsecure configurations.

18. Now that we got the service endpoint id, Let’s create the service and call the execute method as shown below.

The IServiceEndpointNotificationService will provide the Service Endpoint, by passing the service endpoint entity reference to it, we are actually telling the system that we want to access the Two-way end point service registered in the organization.

Once after getting the response, it is up to you where/how you want to use it. For now, I have placed it inside the Description field.

19. Build it and register the plugin. I have registered it against the Quote Pre-create as shown below.

I hope you enjoyed the post, though it is looking as a very big and complicated post, but once if you configure it then you will definitely feel it is pretty straight forward implementation.

In next post, I’ll try to blog about how we can move this console application from the local machine to cloud as a background worker role so that we can ensure it is always up and running.

Happy coding !!

]]>https://ansrikanth.com/2017/04/17/two-way-communication-between-crm-and-azure-service-bus/feed/2Twoway communication b/w CRM And Azure Service BusansrikanthNew Service Endpoint RegistrationDynamics CRM and Azure Service Bus Integrationhttps://ansrikanth.com/2017/04/09/dynamics-crm-and-azure-service-bus-integration/
https://ansrikanth.com/2017/04/09/dynamics-crm-and-azure-service-bus-integration/#commentsSun, 09 Apr 2017 09:36:28 +0000http://ansrikanth.com/?p=1676This post is literally the outcome of 2 days struggle to achieve a two way communication b/w Dynamics CRM (I think I should say 365 now) & Azure service bus. One of the main problem I faced is lack of material that describes integration with new azure portal. Even the MSDN & SDK both are referring to old Azure portal and moreover they are describing with ACS Authentication/authorization to establish Two way communication, which I’m afraid is deprecated now as per this MSDN article. Thought it would be helpful if I blog my experiences for all the individuals over there who are struggling to get the integration work.

One last point before jumping into the actual work. I can directly start with two way communication but that might cause trouble for beginners of this topic. Henceforth, I would like start it from the basics of it and so the post will extend in to multiple parts (hoping it would be 3 to 4 parts).

You can consider this as Part 1 of the series.

To start the integration, I would expect you to be ready with a CRM organization and with Azure subscription. Trail versions of Azure & CRM are good enough to start with. Click here for Azure Trail Subscription and here for CRM Trail subscription.

For Azure trail account you might have to provide your credit card to which they will charge couple of bucks and refund immediately. After the trail period, you have to subscribe explicitly if you want to continue using it for which you have to pay(I mean, they won’t extend the subscription automatically).

Creating Service Bus in Azure

Navigate to Azure portal with your credentials, Click [+ New] on top left corner of the portal and search for service bus.

Search for Service Bus

In the resultant blade, Click on Service bus and then click on Create in next blade.

Provide the namespace and other details as requested. Here are my details just fyr.

Create new service bus

It might take few seconds to create the service bus and get it ready for your usage. And if you selected “Pin to dashboard”, you should be able to see a tile in your Azure Dashboard. If not, then you should be able to see it in the “All resources” tile of Dashboard.

Now that we have our Service bus ready, lets create a queue where our messages come and sit for the listener to process.
A “Sender” is the one who sends messages to the Queue, in our case it would be Dynamics CRM and a “Listener” is the one who keeps an eye on the Queue and processes it accordingly. In real world, this can be a console application or a worker role or any other application that can communicate with the Queue.

Click on the “+Queue” button in the Service bus screen (ideally when you create you should be landing on to the service bus details screen, if not click on the Service bus tile to open the service bus details) provide the queue detail. My queue details are

Create New Queue

Once after creating the Queue, Click on the Queue from the list to open the Queue details blade. We need to generate an access key (SAS Access key) for this queue so that we can provide the connection details to other applications (like CRM) to communicate. This is what also called as “Authorization”. Read more details about it over here. Click Add button to add new shared access policy as shown below.

Shared access policy for Queue

Give policy name some thing like “ReadWriteToQueue” and provide only “Send” and “Listen” permissions to the queue. Note that, We won’t be giving Manage access to any one, with which they can go ahead and delete the queue as well if they want.

Once after creating the policy, if you open the policy you should be able to see the Connection string and Primary key, Secondary key of the queue. Keep them safe with you. Any one with this key details now can send and listen your Queue. So, please be careful while sharing the details. Btw, you have the feasibility to change the key if you think your key is compromised but that attracts change in all your applications to change the key. (Don’t worry, I have regenerated my keys below :))

Primary Key and Connection string of Queue

Now, we are ready with our service bus and Queue. Let’s start the integration with CRM now first and then we will see the listener application. Open the Plugin registration tool (hoping you have already downloaded the SDK). Connect to your organization and click on New -> Service end point registration as shown below. (You can even use Ctrl+E if you are a key board player )

New Service Endpoint registration

Select “Let’s start with the connection string from Azure service bus portal” option and enter the Primary key connection string we got in step #9. (Tip : You can click on Copy button beside the connection string to copy the full connection string in 1 click). Click Next button after pasting/entering the connection string.

You should be able to see all the connection details (service bus name space, SAS Key name etc), Ensure the details are correct and Click Save button.

Service Endpoint registration confirmation

Register a new step like how we will create for any other plugin assembly. Notice that, you can not register a synchronous step. It should always be an asynchronous job. For now, I’ve registered it on Contact Post create (Async).

Register message against Service End point

With this, we are done with the changes required from CRM (sender) end and even from the Service bus end. The result of these steps is Whenever we create a contact record, CRM will send the full context information (Like how we get PluginExecutionContext) as a message to Azure service bus Queue which we defined. Let’s quickly test how it is working by creating a contact. Here is the result I found when I created a contact in My CRM organization.

Queue Messages in Azure service bus

Now that we are done with the Sender part of the process, lets quickly create a simple console application to see what is the messages we got. Create a new Console application project, Add “WindowsAzure.ServiceBus”, CRM Libraries Nuget reference to get the libraries related to Azure service bus and CRM.

Here is the code that you can use as it is to get the data in the message and it is pretty much self explanatory.

QueueClient is one of the AzureServiceBus classes which can help you in listening the messages that are coming to the specific queue (if you observed the connection string, the end of the connection string you can see the Queue which we are attaching this listener).

The OnMessage of Queue Client is like an event driven method which will trigger the call back function whenever there is any incoming message to the attached queue.

Inside the call back function it is just some random code I used to display the context details. You can see, we will be getting full context of the primary entity like how we will get in Plugin. Notice the usage of RemoteExecutionContext, this is the object that we will get from the service. You should be replacing this with your relevant code. Following is the o/p of my console application for your quick reference.

Output from Azure Service bus Queue

Note: You can use Shared variables as well, if you want to pass the information of any other related entities.

Also, the main advantage of using Queueing & service bus mechanism is to decouple the logic. So, don’t try to access the CRM from your Console application again, rather use the shared variables or custom classes to pass the required information from CRM to Queue.

With this we are done with the first part of the integration with Azure service bus & CRM. This is what the OOB and pretty straight forward integration which can fit in many of the default scenarios.

Hope, you enjoyed the post. I’ll try to quickly blog the next posts as well, where I’ll be discussing about Twoway integration with CRM and using worker role to host the service in side the Azure.

]]>https://ansrikanth.com/2017/04/09/dynamics-crm-and-azure-service-bus-integration/feed/4Queue Messages in Azure service busansrikanthSearch for Service BusCreate new service busCreate New QueueShared access policy for QueuePrimary Key and Connection string of QueueNew Service Endpoint registrationService Endpoint registration confirmationRegister message against Service End pointQueue Messages in Azure service busOutput from Azure Service bus QueueCRM-Sharepoint integration with Sharepoint REST API using Custom Workflow – C#https://ansrikanth.com/2017/03/13/crm-sharepoint-integration-with-sharepoint-rest-api-using-custom-workflow-c/
https://ansrikanth.com/2017/03/13/crm-sharepoint-integration-with-sharepoint-rest-api-using-custom-workflow-c/#respondMon, 13 Mar 2017 10:47:37 +0000http://ansrikanth.com/?p=1582Working for a client last week where in we got a requirement to create a Sharepoint list item when a new Lead is created in CRM.

Being a CRM Resource, I have first checked the options (OOB/configurable) available for me and the first thing that came in to my mind is Microsoft FLOW. A quick POC proved that it is very easy to configure CRM & Sharepoint integration with FLOW. However, the first hit for us using the Flow is the additional licence (and surprised to see a max of 15000 runs are allowed with “premium” kind of license, happy to be proved wrong on this).

With a No-go to FLOW then we started our thought process towards REST Apis, initially I found the sharepoint rest apis are a bit confusing (not as straight-forward as CRM’s webapi) but it didn’t took much time to realize that it is just my lack of knowledge on sharepoint made me feel like so. The MSDN Documentation on the Sharepoint rest api is good enough for any one with some basic knowledge on REST to go ahead and do programming with SP.

The first question is how do we authenticate the SP Api ? And a quick googling resulted in to this wonderful blog of Scott TheCRMGuru Durow (MVP) on SP integration with CRM Online. It has every thing one needs to know on how to connect to Sharepoint, the HTTP Helper class to pass the web request. However, the example source code provided by Scott actually creates the Folders in to Sharepoint and so, we had to write our code to create the List item instead of Creating folder.

So, that is what I’m going to explain in this blog – How to Create/Update sharepoint list item from CRM. I have just tried to put some error handling on top of the Scott’s “open source, free to use” library and have published in to Github. I don’t think I can explain all the bits of SP integration over here, rather I’m going to concentrate only on the bits that every one needs to know to further customize it according to their entity/list item.

I have created 2 custom workflow activities (one for Create and another for Update) and here is the quick view of Create Workflow source.

public override void ExecuteCRMWorkFlowActivity(CodeActivityContext context, LocalWorkflowContext crmWorkflowContext)
{
// You might want to work on configuring these 3 settings - URL, User Name, Password !!
ISharePointService spService = new SPService("https://xyz.sharepoint.com", "user@xyz.onmicrosoft.com", "password");
// These are the are part of Sharepoint List Item. Think of better way to handle
// the field changes.. !!
Dictionary<string, string> fields = new Dictionary<string, string>();
fields.Add("Title", Title.Get(context));
// This is the list name what we see in the Sharepoint.
// You might want to keep it as configurable value !!
var result = spService.CreateListItem("Leads from CRM", fields);
Success.Set(context, result.Success);
if (result.Success)
{
ListItemId.Set(context, result.ListItemId);
}
else
{
ExceptionDetails.Set(context, result.Exception.ToString());
}
}

The first line of the code, provides an established connection to the given Sharepoint site. Note that, I have hard coded the Sharepoint URL, User Id & password in this source code. You might want to store them as part of some “configuration” entity in your organization and retrieve it. (You might want to give some thought process further on how do you secure your Password).

The second line is where I’m creating a list of key value pairs to hold all the fields and values of sharepoint record that we are going to create. This dictionary in later stages will be converted in to JSON string to pass as Data parameter to Sharepoint rest api. If you can see, I have only one field to create the list item record (ie Title). You might want to place all your other fields of list item record over here and think on how do you grab these fields from CRM. If there are too many no.of fields, then I would suggest to retrieve the record and map it accordingly instead of placing all the fields as InputArguments.

The next line is the “Go” command to create sharepoint list item with the given information. There is one change you have to do in this line is, The list name. Notice, I have hard coded the list name as “Leads from CRM”, this could be any thing in your case. so I would highly recommend you to place it as a configurable option or as a InputArgument.

The result object provides the Success status of the REST Api call as True/False. You might want to use this in your workflow and take necessary actions in the workflow before taking any other actions.

Here is a quick view of my work flow in CRM.

CRM Workflow to create Sharepoint List Item

Notice, How I’m checking the Workflow Successfully Executed status to update the lead !! A quite common question at this point is, why do we need to update the Sharepoint ID in CRM ? This is required particularly in my case as I also have to ensure that the record is in sync going forward i.e. If any one updates the record in CRM then I have to update in SP as well (thank god it is not vice versa, else I think I should look for a SP Resource :))

For the purpose of Updating SP list item record, I have created another CodeActivity with almost the same piece of code except this time it is a MERGE request to SP Api. This is how my Update Code activity looks like.

public override void ExecuteCRMWorkFlowActivity(CodeActivityContext context, LocalWorkflowContext crmWorkflowContext)
{
// You might want to work on configuring these 3 settings - URL, User Name, Password !!
ISharePointService spService = new SPService("https://xyz.sharepoint.com", "user@xyz.onmicrosoft.com", "password");
// These are the are part of Sharepoint List Item. Think of better way to handle
// the field changes.. !!
Dictionary<string, string> fields = new Dictionary<string, string>();
fields.Add("Title", Title.Get(context));
// This is the list name what we see in the Sharepoint.
// You might want to keep it as configurable value !!
var result = spService.UpdateList("Leads from Flow", ListItemId.Get(context), fields);
Success.Set(context, result.Success);
if (!result.Success)
{
ExceptionDetails.Set(context, result.Exception.ToString());
}
}

No much difference to the previous code. I don’t think I need to go through this code again. And the Update workflow is

Update Sharepoint list item from CRM Workflow

Isn’t that simple ?

So, What you have to do now to get it done further ? Nothing much, Download the source code from here or from my GitHub, Build it and register it as custom workflow activity (after doing required URL, user/password changes and the list name changes). Create a workflow (Realtime/Asynchronous) as shown. That’s it, you are good to go.