Oct 21, 2023

Can Fetch Xml Builder be used to extend the limitations of Dataverse views ?

Base of Views in Dataverse is actually fetchxml. Views got limitations. Not all the features of Fetchxml being used in creation of views. In other hand Fetchxml builder allows filter data based on complex fetchxmls and it allows creating views in Dataverse based on them. Someone would thing, just as I did, this can be a way to views with more complex criteria. Hm.. lets find out. 

Lets take this example. We have below hierarchy of entities.

Out requirement is to create a view of Sub Depots where Account Category = Distribution and you need to show both Sub Depots against the Account Name.

Lets try this in Dataverse OOB capabilities. 


Though you can easily set the criteria, you will not be able to show the Account name since Account entity is 3 hops away as per the given hierarchy of entities. You are only able to show just two levels. In this case, Sub Depots and Depots.

Lets try Fetch Xml Builder of Xrm Tool Box.


And Results showing without any issue.


Now we will try our next step of transferring this same Fetch to Dataverse. 

Now select Save View as option;


Then you get below option to select if you need a personal or system view.


Then you are allowed to give a name to the new view.


View is now created.

Lets try the view now in Dataverse. When you check the fields you will see Dataverse is throwing a error saying these Account fields to be removed,


If you try to run as it is, it will through below error message.


Conclusion

NO! 
You cannot use Fetch Xml Builder to create Views in Dataverse that extends the limitations.

Oct 18, 2023

Write a Custom API and call from Workflow

A Custom API is comparatively a new mechanism to create your own API in Dataverse. This is like a Action where you can package few steps to accomplish something. Advantage is you can then call from anywhere, either client side or server side etc. Obviously it can be called via a workflow or Cloud Flow too. Custom API is more flexible since coding is possible.

In this scenario we will see how to create a simple Custom API and call it from a classic workflow.

Writing a Custom API

1) We need to write a code which is pretty similar to a Plug-in. This is where we define our logic. In my case I am accepting a parameter string (i.e. DetailStr) and update Description (i.e. so_description) field of the custom entity called Office (i.e. so_office).

namespace AccAdmin.Plugins.CustomApi
{
    public class UpdateOffice : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context;
            IOrganizationServiceFactory factory;
            IOrganizationService service;

            try
            {
                context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
                ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

                if (!context.InputParameters.Contains("DetailStr"))
                    throw new InvalidPluginExecutionException($"DetailStr not designated or Invalid..");

                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is EntityReference target)
                {
                    if (target.LogicalName != "so_office") return;
                    factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                    service = factory.CreateOrganizationService(context.UserId);

                    Entity entity = new Entity();
                    entity.LogicalName = "so_office";
                    entity.Id = context.PrimaryEntityId;
                    entity["so_description"] = (string)context.InputParameters["DetailStr"];
                    service.Update(entity);
                }
            }
            catch (FaultException<OrganizationServiceFault> e)
            {
                throw e;
            }
            finally
            {
                service = null;
                factory = null;
                context = null;
            }
        }
    }
}

2) Once register the Plug-in, Custom API step will be visible as a step as below.


3) Now we start configuration. First add new Custom API to your solution.
    

Once save my Custom API was seen like below. It will have an unique name which we use to call this. We have set Enable for Workflow = Yes since we plan to call this from a Workflow. Most importantly, we have set our Plug-in step as the Plugin Type which is the linking point of our logic to the API. 


* Idea of all other settings

4) Same way we added the Custom API, we now add a parameter to our solution. Parameter is optional. In our case we plan to pass a string parameter.


Once created, parameter was seen as below. Nothing complex about this. You may notice we have selected Custom API we defined in previous step is set here for Custom API field.


Now we are done with our Custom API

Calling the Custom API from Workflow

Here I am create just an On Demand workflow so we can easily check it.

5) I am initiating a very simple Async workflow against Office entity.


6) Now I am adding a step of performing an Action. Interestingly, when I check the list of available Actions, I am seeing my Custom API by its unique name.


I see two parameters here. One is Target where we need to pass the current office record. Other one is what we define in Custom API which is needed for our logic.


7) Now its a matter of running our Workflow On Demand for any selected Office record.

* 
Unique Name: Unique name for the Custom API (Start with the publisher’s prefix which you have specified on your solution).

Name: Name for the Custom API.

Display Name: Display Name for this Custom API. In case we have enabled multi-languages on the System, we can provide a specific name for the custom API based on the language.

Description: This field is to store the description of this Custom API.

Binding Type: The Binding Type is the Options set field and could be set as Global, Entity, and Entity Collection. This should be specified as per your operation requirement (Entity Collection is only supported in Function Type Custom API).

Bound Entity Logical Name: This field is required when we select the Binding Type as Entity or Entity Collection. For the binding type as Global, it can be empty.

Is Function: It defines whether your custom API is a Function (this can only be called using Get Method) or Action (this can only be called using POST method).

Is Private: To define the Custom API is private or public (setting it private makes it accessible to only the owner of the Custom API).

Allowed Custom Processing Step Type: Allowed Custom Processing Step Type is another Option set field with options like None, Async Only, Sync, and Async. These options let you define whether the other plugins could be registered on this Custom Message and also lets you define its behavior. Like Async Only allows the plugins to register only onPost operation with Execution Mode to Asynchronous, and same for the Sync and Async option.

Execute Privilege Name: We can define the privilege that allows execution of the custom API. As per Microsoft docs, we can also create custom privileges and it is currently in development. We can use OOB privileges, for example,prvCreateLead, prvWriteLead, etc.

Plugin Type: Set the reference of your plugin for this API.

Warning
This example works fine. Anyway, there has been some deployment issues reported as per now we write this. So it is always advisable to call your Custom API from a Cloud Flow than a classic workflow. That worked perfectly.