There was a little unusual scenario to cover. With user-owned tables in Dataverse (see, I’m practicing different pieces of new terminology in the same sentence ), how do we keep all records under the same team?
You might probably question the scenario to start with, and I’d be happy to just say that there is a hungry team here which wants all the records to itself:
But it’s not that. In this particular situation, this is just how we wanted to control security. There is a business unit, there is a team, and there are users from this and other business units that may need access to the records. Within the business unit, those records can be shared – that’s not a problem. Users can move between business units, they may need to be granted access to the BU data, and they may need to be removed.
It could probably be handled by giving such users a security role, but we may forget to remove roles. So we might give those roles to the team and keep adding/removing users to/from the team. Would not be quite clear what to do with the “owner” field if the users moves to another BU and does not need access to the data.
Plus there is data migration, so all those migrated records have to be assigned somewhere.
Anyway, it’s not necessarily the only option, but it’s an option, so how can we do it?
Well… let’s create a plugin.
Why?
- We can register it in the pre-operation so we won’t need any post-processing to reassign records (which would be the case with Power Automate Flows and/or with the classic workflows)
We can use the same plugin for any entity. Although, we will need to register 3 steps per entity
And what are those steps?
- Assign message (in PreValidation – can’t replace “Assignee” parameter of the request in the later stages)
- Create message (PreOperation works fine – this is where we’ll be replacing “ownerid” column of the record)
- Update message (PreOperation – same note as for the “Create” above)
Since the plugin will be running in Pre stages, it won’t need to consume additional API calls. Instead, it’ll be replacing “Assignee” (or “Owner”) in the incoming requests as they keep coming in.
public void Execute(IServiceProvider serviceProvider) { IPluginExecutionContext context = (IPluginExecutionContext) serviceProvider.GetService(typeof(IPluginExecutionContext)); IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); var teamRef = new EntityReference("team", Guid.Parse("33844034-ac38-eb11-a813-0022483ba225")); if (context.InputParameters["Target"] is Entity) { var target = (Entity)context.InputParameters["Target"]; if (target.Contains("ownerid")) { target["ownerid"] = teamRef; } } else if (context.InputParameters.Contains("Assignee")) { context.InputParameters["Assignee"] = teamRef; } }
And, then, just need to add SDK steps for every entity you want to handle that way. For example, this would be for the “Assign” message:
Of course you could make the plugin more intelligent – for instance, you might want to to look at the specific fields and only assign records to the team when those fields have certain values.
But those would be enhancements, and I just wanted to share basic code here.
Hi,
What is the exact business requirement?
First thing, if you want to share a record with other BU user you can handle it using access team template (Record level security) no need of moving users from one BU to another.
If there is a static team which can shared across environment. We can achieve it using OOB WF. On creation of record assign record to a team through WF step.
Regards,
Prakash
Adding to above reply.
Assign and share are different category altogether in CRM.
If sharing a record through ATT means, owner will not change but still the user who added to ATT can be able to read/edit/delete the record based on privilege we set in ATT.
Assign will change the owner of the record.
Hi, of course you can use access teams, and that’s what you’d normally do in the usual scenarios where ownership matters. Where it does not, or where you just need (for whatever reason) assign everything to the specific user/team, you might also use a workflow – no argument there. You’ll need to register that workflow on assign/update/create. The purpose of the code above is to do that assignment synchronously without doing any postprocessing and without invoking any additional API calls. It’s just more efficient, that’s all.
Hi, We can convert OOB workflow to run synchronously by converting to real time.
Yep, that’s another option. With the plugin, you can write it once and just register steps for each entity where you need this particular logic (does not apply to just any plugin, but the code above is not entity/table – specific). And you can do it in pre-stage, which is different from how workflows will do it (you’ll have to add an assignment step, which will be a separate API call essentially)
Cool ?