Why is my calculated field not showing in rollup field definition?

And I had the same from my customer development team. The first thing I did was go to “Rollup Field” documentation in Microsoft Docs and sent to cross check the below points. After creating calculated fields over the years, I thought this has to be something related to configuration.

image

(Pic courtesy: Microsoft Docs)

Well, if you are wondering why your rollup field is not showing, most likely it is due to first of the two conditions mentioned.

Coming back to our scenario, client confirmed that they have not violated these scenarios. It was bit surprising as I had configured calculated fields in roll-up definition multiple times. So I had no other option but to open their calculated field definition.

And there I found it. What I realized is that beginners starting with roll-up field may make the same mistake too. Although their calculated field was not using other calculated field but they were using a field from parent entity in their calculated field definition.

If I take the second statement –A rollup can’t reference a calculated field that uses another calculated field, even if all the fields of the other calculated field are on the current entity”, one of the implicit perception from this would be – A rollup field can’t reference a calculated field that uses field of the parent entity in it’s definition”.

For experienced consultants, this may come in naturally. But what I realized from my experience is for beginners in Dynamics, they may tend to miss this point. The developer here just spent couple of hours trying to figure this out Smile

Hope this helps!

Cheers!

Debajit Dutta

(Dynamics MVP)

For consultation/ corporate training visit www.xrmforyou.com or reach out to us at info@xrmforyou.com

Our product offerings:

Role based views for Dynamics 365 (http://www.xrmforyou.com/role-based-views.html)

CRM-Sharepoint Attachment uploader and metadata manager (http://www.xrmforyou.com/sharepoint-integrator.html)

Record Cloner for Dynamics 365 (http://www.xrmforyou.com/record-cloner.html)

Multiselect picklist for Dynamics 365 (http://www.xrmforyou.com/multi-select-picklist.html)

Advertisements

{Solved}Why are my CRM SDK Assembly references in Azure functions throwing error? How do I refer my custom assemblies which are not in Nuget?

And this was the complaint from one my customer. Why CRM assembly references in Azure function apps are throwing error? To add to my woes, that was some pretty important functionality running inside those small little functions and alas, the last few runs have failed. It was few months back and at that point of time, I fixed it.

But in a recent training on WebHooks, it seemed to me participants are not aware of this scenario and hence penning this blog for the benefit of my readers.

If you are absolutely new to Azure functions and how to add assembly references in Azure functions, I guess a bit of basic understanding before reading this blog would help.

If you would have developed Azure functions and referenced CRM SDK assemblies, you would done using project.json file. You would have created the file and then added the below JSON in the file to reference CRM SDK’s

{
"frameworks": {
"net461":{
"dependencies": {
"Microsoft.CrmSdk.CoreAssemblies": "9.0.0.7"
}
}
}
}

With azure functions 1.0, this would have worked just fine. At runtime, the framework would read your project.json file and restore the assemblies from Nuget. A detailed description on this by friend and fellow MVP Nishant Rana in this blog.

But the issue starts once Azure functions are upgraded to V2.0. And why? Because project.json is no longer supported in V2.0. Instead a new file – function.proj needs to created and referenced assemblies need to be defined in specific format.

All we need is to add a file with name “function.proj” and put the below contents.

image

<Project Sdk="Microsoft.NET.Sdk"> 
    < PropertyGroup> 
        < TargetFramework>net461</TargetFramework> 
    </PropertyGroup>    
    < ItemGroup> 
        < PackageReference Include="Microsoft.CrmSdk.CoreAssemblies" Version="9.0.0.7" /> 
    </ItemGroup> 
< /Project>

Your function code remains unchanged. But for beginners, you would need to reference with #r directive before using it.

image

Now once you run, you will see that the packages are now successfully restored and the application is working fine.

P.S – I tried at that time with .NET framework 4.6.2 and using <TargetFramework>net462</TargetFramework>. Unfortunately with this version it threw an error. May be I am missing something silly and I would be grateful if readers point this out.

Ok, so my CRM Sdk assemblies are in Nu-get and I can refer them just fine in the new function.proj file. But what about custom assemblies which are not in Nuget. How do I refer them? Well, if that’s the case, you should not be worried. There is an easy way to do this.

For this example, let’s assume Microsoft.Xrm.Sdk.dll is my custom assembly.

In your functions app, navigate to Platform Features –> Advanced Tools (Kudu)

Once inside Kudu, open Powershell prompt

image

Navigate to Site –> wwwroot. Once inside the wwwroot folder, create a new folder called bin

image

image

Go inside bin folder and drag and drop your assembly. In my case it is Microsoft.Xrm.Sdk.dll

image

All set and done. Now we just need to refer this assembly in our code file. As shown in the below screenshot, we can refer it by using a relative path.

image

Now you can start using your assembly. Simple isn’t it?

Honestly this part is not something related to specifically to D365 but with Microsoft’s vision of removing technology barriers, a CRM architect/ developer would  frequently find themselves working on Azure functions and this might be some information which saves some time.

Hope this helps!

Cheers!

Debajit Dutta

(Dynamics MVP)

For consultation/ corporate training visit www.xrmforyou.com or reach out to us at info@xrmforyou.com

Our product offerings:

Role based views for Dynamics 365 (http://www.xrmforyou.com/role-based-views.html)

CRM-Sharepoint Attachment uploader and metadata manager (http://www.xrmforyou.com/sharepoint-integrator.html)

Record Cloner for Dynamics 365 (http://www.xrmforyou.com/record-cloner.html)

Multiselect picklist for Dynamics 365 (http://www.xrmforyou.com/multi-select-picklist.html)

{Solved}–Invalid Argument error while showing Virtual entity using Custom Virtual Entity Data Provider on Unified interface

Virtual entities are there for pretty long time now. And why this done and dusted topic? Sometimes the greatest of surprises come from the simplest of stuffs and this was one such scenario.

So here was my customer IT team who had developed a pretty good custom virtual entity data provider to show up virtual entities in CRM. And they had done it a year back and it was working perfectly fine till they decided to make the switch to Unified interface. While the virtual entity is showing up just fine in classic UI, the Unified interface is throwing an error – “Invalid Argument”

To be honest, my first thought was there must have been some changes made to the code but again if that is the case, how come it is still working in Unified Interface. Searched the heck out of Google but nothing much on the Unified interface. So I decided to try something very simple of my own.

I created a custom Virtual entity data provider and wrote a very simple RetrieveMultiple plugin. No dynamic data and all. Just some adhoc records being returned.

public class RetrieveMultiplePlugin : IPlugin 
    { 
        public void Execute(IServiceProvider serviceProvider) 
        { 
             var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); 
            context.OutputParameters["BusinessEntityCollection"] = this.GetEntities(); 
        }

        public EntityCollection GetEntities() 
         { 
            var entCollection = new EntityCollection(); 
            
            for(var i=0; i < 5; i++) 
            { 
                var ent = new Entity("virtual_demoentity"); 
                ent["virtual_demoentityid"] = Guid.NewGuid(); 
                ent["virtual_name"] = $"Record {i + 1}";

                entCollection.Entities.AddRange(ent); 
            }

            return entCollection; 
        } 
    }

As simple as above. Can’t believe anything can be simpler than this. Registered the assembly as Custom Data provider in plugin registration tool. Set up the virtual entity in CRM. Went to classic UI and I could see my five hardcoded records right up there. Piece of cake.

image

Not that I can say of when I navigated to the same Virtual entity on Unified interface.

image

And finally from one expert, got hold of a piece of code which was working. Honestly when I started comparing, for first few passes could not even find the reason. Finally one line caught the eye. And I  made the change from

var entCollection = new EntityCollection();

to

var entCollection = new EntityCollection( { EntityName = “virtual_demoentity”} );

Uploaded it now and it ran just fine in Unified interface as well.

image

So remember, if you are getting this error in Unified interface after designing your Virtual entity data provider and the same is working fine in classic UI, make sure you double check that while creating the instance of EntityCollection, you specify the “EntityName” property.

Hope this helps and saves you some hours for this silly one.

Cheers!

Debajit Dutta

(Dynamics MVP)

For consultation/ corporate training visit www.xrmforyou.com or reach out to us at info@xrmforyou.com

Our product offerings:

Role based views for Dynamics 365 (http://www.xrmforyou.com/role-based-views.html)

CRM-Sharepoint Attachment uploader and metadata manager (http://www.xrmforyou.com/sharepoint-integrator.html)

Record Cloner for Dynamics 365 (http://www.xrmforyou.com/record-cloner.html)

Multiselect picklist for Dynamics 365 (http://www.xrmforyou.com/multi-select-picklist.html)

Unearthing “Solution Layering” feature of Dynamics 365. How are the good old concepts of patching and cloning related to it?

If you really ask me, solution layering is not a functionality in itself. Rather it is a visual representation to see the order in which a solution changed the component. Since you have visual representation of how a component got modified during the course of deployment of multiple managed solutions, this can be used for troubleshooting as well.

I am not going to explain what is Solution Layering. The feature is explained in Microsoft Docs and many other wonderful blog posts. What I am going to explain here is how you can use this feature to your benefit. Believe me the concept of solution layering has always been there starting since 2011, first with managed solutions and then with CRM 2016 it got even more intricate with the introduction of solution patching and cloning. Till now the concept was running behind scenes but there was no way to visualize it. Well with Solution Layering you get just that and let’s see how.

I take the simplest of example. I take the Contact entity and play with the “First Name” field. And believe me with this example I can show you the entire solution layering visual involving patching, cloning and everything. So let’s get started.

Step 1:

Create a solution – Let’s call it “Sol A”. Version 1.0.0.0. Add the contact entity with just “First Name” field. Change length of “First Name” field to 100. Export the solution as managed and import it in target environment.

image

Open the target environment default solution and go to Contact–> Fields –> First Name. Select the field and from the top menu, click on “Solution Layers”. Why did I go to default solution? This is because solution layers is only visible for unmanaged solutions. And when default is present already why bother to create an unmanaged one for this demo.

image

image

This is our first glance of Solution Layering screen. As you can see ‘Sol A’ is at the top order indicating that the length specified for ‘Account Number’ field in Sol A is what in force. Awesome!

Step 2:

Now we repeat Step 1. Create solution named “Sol B”. Version 1.0.0.0. Add the “Contact” entity with just “firstname” field. Change length of “First Name” field to 200. Export the solution as managed and import it in target environment.

Now if I see Solution layering for the field in target environment, as expected you can see Solution B is of the highest order now indicating that changes coming in Sol B are now in effect. Is this something new in here? The answer is a BIG NO. We all know that managed solutions are stacked in order of import (not always and will come to that in a moment) and hence changes coming with Sol B are in effect here. Could I visualize this previously? NO. Solution layering does just that.

image

Step 3:

Now repeating our step of creating solution one more time. We now clone Sol A. Set the version number to 2.0.0.0. And change the length of the field to 250. Remember we already have a lower version of the solution already installed.

image

Now we export it as Managed and then import it in the target environment. Now this time the behavior is bit different. This time we get a different option whether we want to maintain customization or overwrite customization. Let’s first choose “overwrite customization”.

image

When the solution is now imported in the target environment, check for solution layers, you can see something different. You can see in the order in which the unmanaged solution is the doing the final honours here. Which is again something we know would happen as we choose overwrite customizations. But could not visualize before Solution layering was not available.

image

Step 4:

Now what we do. We open Sol B and then change the first name field to 300. Export it and then import it in the target. This time we maintain our customizations.

image

If we check the Solution layering now in the target then nothing new in here. We can see Unmanaged layer at the top again taking all the accolades.

image

Step 5:

Now something very important. We create a patch solution of Sol A.  Add the contact entity and the First Name field. Change the field length to 450.

image

Export it as managed and import it in the target environment. If I open Solution layering now, you can see the managed patch right above it’s base Sol A. Is this something new here guys? No it’s not. After all we all know that managed patches sit on top of base solution. But when I see this through solution layering its a treat. The patch just sits above Sol A and below Sol B.

image

And before I end this as I said at the start. Solution layering just gives a wonderful visibility of how the managed solutions are stacked up. And how a components’ final behavior is affected by multiple solutions imported here. The logic of the inner workings now get a wonderful UI to visualize.

Hope this helps!

Debajit Dutta

(Dynamics MVP)

For consultation/ corporate training visit www.xrmforyou.com or reach out to us at info@xrmforyou.com

Our product offerings:

Role based views for Dynamics 365 (http://www.xrmforyou.com/role-based-views.html)

CRM-Sharepoint Attachment uploader and metadata manager (http://www.xrmforyou.com/sharepoint-integrator.html)

Record Cloner for Dynamics 365 (http://www.xrmforyou.com/record-cloner.html)

Multiselect picklist for Dynamics 365 (http://www.xrmforyou.com/multi-select-picklist.html)

“Team Members Privilege Inheritance”–What is this doing in Security role screen of Dynamics 365?

My team mate had the same question for me. He was in the middle of preparing demo with the customer and he opened up Sales person security role to make some modifications and guess what, he sees something new in there. Just like the one in below screenshot.

image

A new option with two values – 1) Default – Team Privileges only & 2) Direct User (Basic) access level and Team privileges.

To be honest, I didn’t get much from the options. So I fell back to my bible – Microsoft Docs. And this is what I found.

There has been few times when even after reading Microsoft Docs I could not get much and this was one of them. I was not able to understand much but what I could get is it has to do something with Azure AD groups. Before continuing further to understand this, you should first understand that Azure AD groups (Office 365 & Security) can now own records in Dynamics 365. I have detailed this in my blog here. I would suggest you understand that first before continuing.

We all know that a user in Dynamics 365 inherits security privileges from the teams it is associated with. First things first, this option we are talking about is only valid when a user inherits security privileges from Azure AD Office 365 team or Azure AD Security team in Dynamics 365. This option is not valid for owner teams.

Now that we have limited the set, what is this feature all about? For a long time Dynamics 365 had a peculiar behavior that there there must be a security role explicitly assigned to user even though the user may be part of multiple teams which have security roles and privileges to access Dynamics 365. If the user logs in, he would get an error like the screenshot below.

image

I have explained this in my blog some time back – Can a user work only with team roles in Dynamics 365. So to make it work you just needed to assign a security (dummy one) explicitly to the user. It does not matter whether the security role has any privilege or not.

This setting takes care of just this in case of Azure AD Office 365 and Security Team. If you set the option “Direct User (Basic) access level and Team privileges”

CRM would no longer throw an error even if no security roles are explicitly assigned to the user. The user can just work with team roles in Dynamics 365. If we keep the default option – “Default – Team Privileges only”, it falls back to the same behavior where an explicit role is required by the user to work with CRM.

Please note that for traditional owner teams this has no effect.

Hope this helps!

Debajit Dutta

(Dynamics MVP)

For consultation/ corporate training visit www.xrmforyou.com or reach out to us at info@xrmforyou.com

Our product offerings:

Role based views for Dynamics 365 (http://www.xrmforyou.com/role-based-views.html)

CRM-Sharepoint Attachment uploader and metadata manager (http://www.xrmforyou.com/sharepoint-integrator.html)

Record Cloner for Dynamics 365 (http://www.xrmforyou.com/record-cloner.html)

Multiselect picklist for Dynamics 365 (http://www.xrmforyou.com/multi-select-picklist.html)

Azure AD Groups can own your Dynamics 365 records. Learn it how?

Just another day in office and just another new stuff to learn. I bet this one will excite almost all the CRM consultants worldwide.

So what I am talking about in here. Well I am talking about “team ownerships”. I think it is being used in almost every project I have come across till date. Teams are integral part of CRM security and none can deny it. You may be thinking – “come on debajit. We play with this stuff day in and day out. what new are you going to tell us”. If you are aware of the latest feature where Azure AD groups can own Dynamics 365 records, well nothing new in here. But in case this is sounding new, believe me you are in for a fun ride.

Let’s start with a revelation – Now Azure AD groups can own records in Dynamics 365. All this time there used to be owner teams. Now both Azure AD office and security group can own your business records. Let’s see how.

So here I login to the https://portal.azure.com. Choose the active directory for my CRM instance and click on “Groups” menu item on the left bar.

image

Let’s create a new group.  Below are the group details. I have chosen Group Type as “Office 365”. However you can choose the other option “Security” as well.

I also add one member “CRM User 2” to the group.

image

So I have my new group created. Observe the Object ID field value I have highlighted in the below screenshot. If you remember, I told that this Office 365 security group can now own records in Dynamics 365. And Object ID value is going to be of prime importance to set that up.

image

I login to CRM –> Settings –> Security –> Teams –> New Team.

Details of the team specified below. I have chosen then team type as “AAD Office Group” and in the Azure AD Object Id field, I have put the Object ID copied from the previous step.

image

Save the team. CRM will validate the Object ID entered. Please note that you cannot add members to the team from Dynamics 365 screen. To add a member to the group, you would need to do that from the Azure portal or Office 365 admin screen.

image

So my team is saved. As you can see, there is no “+” icon in the Team Members section. It may take a moment to refresh the team members from Azure. If it doesn’t there is another trick up my sleeve which I am going to share with you soon. Let’s hold on to that for a moment.

So now I have team that represents a Office 365 group. The next step is to go ahead and assign security role to it. I click on Manage roles and assign “Sales Manager” role to it.

image

If you team members section is still not refreshed and does not show the user you added there in the portal, no worries we will get it sorted out.

So now you have a team which has members (we know it is there as we added in the portal) and has security role. So let’s make it own a record.

I go to Accounts and choose any account and then click on Assign. As you can see from the below screenshot, you can choose your Office 365 team you just created.

image

Works like a charm. Now office 365 admin can just manage groups from Office 365 admin screen or Azure portal, add or remove members from the team and all this will be automatically reflected in Dynamics 365 without the need of the Office 365 admin to login to Dynamics. Wonderful isn’t it?

image

Alas, till now “CRM user 2” whom I added to this group in Azure portal is not reflected. No worries, now it’s time to make it work.

I login to Dynamics 365 with CRM User 2. First time when I login, I see something like this. No Accounts, Contacts or other entities which I should have access by virtue of team roles.

image

But if I go back to my team now, I can user CRM User 2 added. Don’t know if it is a bug or behavior but it automatically gets refreshed in CRM when the user logs in.

image

Coming back to CRM user 2 screen, if I just refresh the page everything falls back to as desired.

image

I believe it’s a great feature and will be certainly helpful for many CRM consultants whenever they design security for their implementations.

Hope this helps!

Debajit Dutta

(Dynamics MVP)

For consultation/ corporate training visit www.xrmforyou.com or reach out to us at info@xrmforyou.com

Our product offerings:

Role based views for Dynamics 365 (http://www.xrmforyou.com/role-based-views.html)

CRM-Sharepoint Attachment uploader and metadata manager (http://www.xrmforyou.com/sharepoint-integrator.html)

Record Cloner for Dynamics 365 (http://www.xrmforyou.com/record-cloner.html)

Multiselect picklist for Dynamics 365 (http://www.xrmforyou.com/multi-select-picklist.html)

CreatedOn, CreatedBy, ModifiedOn and ModfiedBy– All you need to know to maintain history during Data Migration in Dynamics 365

These are the days of PowerApps. Canvas Apps, Model driven apps, flows and myriad of new features which are introduced lately or over the past couple of years. And yet in day-day jobs in our client projects we tend to argue over mundane things which in-fact I remember discussing during my initial days in CRM with 2011 version.

And one of them is data migration from one system to another maintaining their history. Whenever we talk about history, the bone of contention are the below four fields

  • CreatedOn
  • ModifiedOn
  • CreatedBy
  • ModifiedBy

We always suggest that any type of data operation should go through CRM SDK. Off course there are scenarios where you would perform DB to DB data migration but barring those scenarios it is always through SDK whether it is through batch JOB, plugin or SSIS Data adapter.

And here I was confidently updating my customer that we would be maintaining the history of all mentioned fields. However I get a stern objection saying while we can maintain the created on, we can’t do so for the remaining fields. And without wasting much time in argument I referred this wonderful blog written by the wonderful Aileen Gusni on the same topic way back in 2014 and it still holds good today! I was a big fan of her blogs during those early days in CRM and I still believe that she had one of the best content if not the best I have ever come across.

Coming back to the topic, the blog clearly mentions that you can maintain history for all of this. But still I was getting complaints that whatever code suggested there doesn’t work. And that is because we fail to understand the context where the code to set custom values for these four fields would work. If you have already understood the context, no need of reading further. Aileen’s blog is good enough!

But if you are still in doubt, here we dive deep.

Scenario 1: Create a console app and modify the fields using SDK.

var createEnt = new Entity("account");

createEnt["name"] = "Data Migration Create from Console";

createEnt["overriddencreatedon"] = new DateTime(2018, 03, 01);
createEnt["createdon"] = new DateTime(2017, 03, 01);
createEnt["modifiedon"] = new DateTime(2018, 03, 01);

// below is the GUID of one crm user named – CRM User 1
createEnt["modifiedby"] = new EntityReference("systemuser", Guid.Parse("67312B4B-9265-E911-A9BA-000D3A33BCD9"));
createEnt["createdby"] = new EntityReference("systemuser", Guid.Parse("67312B4B-9265-E911-A9BA-000D3A33BCD9"));

service.Create(createEnt);

As of the day I am writing this blog, it is 12th of May, 2019.

Below is the snapshot of record I just created.

Let’s concentrate on the first field – “Created On”. As you can see CreatedOn is field is set to the custom value I set. But wait, it is set to 3rd of March, 2018. If you observe the above code sample, I have set two fields for “Created On” field.

createEnt["overriddencreatedon"] = new DateTime(2018, 03, 01);
createEnt["createdon"] = new DateTime(2017, 03, 01);

And it is the value of “overriddencreatedon” field which is taking effect here. So remember – “If you are trying to maintain the historical createdon value during data migration using CRM SDK from external application, it is the value of “overriddencreatedon” field which is important.

The other fields “ModifiedBy”, “ModifiedOn” and “CreatedBy” were set based on runtime values and whatever set in the code had no effect. So if you are trying to maintain historical data from these fields during data migration using SDK methods from external application, you would not be able to do so.

image

Scenario 2: Set values inside a plugin on pre-create.

Here I do the same code stuff but this time I do it in the pre-create of Account. Here is the code sample.

public void Execute(IServiceProvider serviceProvider)
         {
             var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
             var target = (Entity)context.InputParameters["Target"];

            target["overriddencreatedon"] = new DateTime(2017, 03, 02);
             target["createdon"] = new DateTime(2017, 03, 01);
             target["modifiedon"] = new DateTime(2018, 03, 01);

   // Guid of CRM User 1
     target["modifiedby"] = new EntityReference("systemuser", Guid.Parse("67312B4B-9265-E911-A9BA-000D3A33BCD9"));
     target["createdby"] = new EntityReference("systemuser", Guid.Parse("67312B4B-9265-E911-A9BA-000D3A33BCD9"));
       

}

This time I create the record using UI. Below is the snapshot of the record after I create it.

image

Whoooo! All my custom values are taking effect here. And notice here, overriddencreatedon this time has no effect. It is the createdon value which is reflecting now. So all you need to do to maintain history for these four fields is set the value in the pre-create pipeline. Whether you are importing, creating from console or using SSIS data adapters, the plugin would fire and this would take effect.

Scenario 3: Set values inside a plugin on pre-update.

I am not going deep here. But this would perform the same like pre-create. I am not sure which scenario you would like to use pre-update to update these historical fields. But the just from the holistic point of view this would work exactly like pre-create.

Scenario 4: Using update Method of SDK.

If you are setting these fields using service.Update method of SDK, this would not take any effect. Even the created on won’t work this time unlike our first scenario no matter if you set the createdon or overriddencreatedon field.

Hope this helps next time you do data migration.

Debajit Dutta

(Dynamics MVP)

For consultation/ corporate training visit www.xrmforyou.com or reach out to us at info@xrmforyou.com

Our product offerings:

Role based views for Dynamics 365 (http://www.xrmforyou.com/role-based-views.html)

CRM-Sharepoint Attachment uploader and metadata manager (http://www.xrmforyou.com/sharepoint-integrator.html)

Record Cloner for Dynamics 365 (http://www.xrmforyou.com/record-cloner.html)

Multiselect picklist for Dynamics 365 (http://www.xrmforyou.com/multi-select-picklist.html)