Showing posts with label Dataverse. Show all posts
Showing posts with label Dataverse. Show all posts

Aug 17, 2026

Zapier as an integration platform for Dynamics

Recently came across Zapier integration platform and was keen on checking if it works with Dynamics/ Dataverse. So I tried one simple Zap (Zap is just one integration workflow within Zapier). Just like any other technique, such as power automate, Zapier too produces plethura of connector to select from.

As per this writing, Power Automate/ Cloud Flow is the way to accomplish many integration workflows in Power Platform, however Zapier got much wider selection of connectors and ease of connectivity. Hence, Zapier can be the way to go depending on third party app you may need to integrate with.

In my example, I would like to create a Dataverse Contact when I add a contact to my Google Contact.

A. Building the Zap

I added the Google Contact as the connector and New Contact as the trigger.


Then I added Dynamics 365 Connector and Create Contact as the Action.

I am able to map frield comming from Google Contact as I wish. I can even add hard coded values of any field. (Ex. Ownership of record)

It also help testing under a different Tab as below.


Now its a matter of giving a suitable name for the Zap and publishing.

B. Advantages

1. Zaps can be arranged in a hyerarchical folder structure for improve useability

2. Change History of the Zap is logged.    

3. Run History is saved and can be illustration is available.

4. Version Contraolling 

5. Can use current Zaps as a Template for developing of new ones.

Jul 10, 2026

Call Azure Function directly from Plugin

This is step by step guide to explain how to call an Azure Function directly from a Plugin. When I say diretly, we do it in the code level. Other way of doing it is via  webhook. Lets jump in.

Scenario

When we create a Contact in Dataverse (model-driven app), I need to register the contact in the financial system which is best done using an Azure Function. So Approach is I am writing a pre create plugin for Contact which should call Azure Function to get the registration done. For this I am passing Contacts' full name to the function and expecting registration numbers to be passed back to Dataverse.

Create Azure Function

(Refer: https://www.youtube.com/watch?v=NhhmLt0YGqY&t=218s for step by step create of function app)

Here I retrieve name and returning registered number back. (Registering logic is not implemented but to ocestrate the action I am generating a randon number as registration number)

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

namespace Sume4FunctionApp;

public class SumeFunction1
{
    private readonly ILogger<SumeFunction1> _logger;

    public SumeFunction1(ILogger<SumeFunction1> logger)
    {
        _logger = logger;
    }

    [Function("SumeFunction1")]
    public IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req)
    {
        // Retrieve Value
        string name = req.Query["name"];
        _logger.LogInformation($"Azure Function retrieved: {name}");

        // Logic
        // TODO - Register name in Financial System
        string FSID = Guid.NewGuid().ToString("N")[..10];

        // Retern Reg Number 
        return new OkObjectResult(FSID);
    }
}

After local testing, publish the Azure Function in Azure.


Now you can see the Azure Function under Function App.


Under Function Keys, you can retrieve the code which will be used in Plugin code.


Create Plugin

Now its time to call the Azure Function from Plugin code. Plugin is registered in Pre Create with below settings.


Notice how I compile the full name to be passed to function. Also how I retrieve the registration number and set to relevant field which will be populated (since we are in pre-stage just assigning is enough). Notice below steps;

  • We create a class with contact name as attribute to be passed to serializer
  • Serviceurl consist of below 3 components
    • Site Address (from Azure registration of Function App)
    • Function name (As we know from the code)
    • Code (read from function)
(Refer https://www.youtube.com/watch?v=KdGZ2Oo-4L8 to get explanation of steps)

if (execCtx.InputParameters.Contains("Target") && execCtx.InputParameters["Target"] is Entity target 
    && target.LogicalName == "contact")
{
    // Retrieve Name
    var contactDetail = new ContactDetail();
    string firstName = target.Contains("firstname") ? target.GetAttributeValue<string>("firstname") : string.Empty;
    string lastName = target.Contains("lastname") ? target.GetAttributeValue<string>("lastname") : string.Empty;
    ctx.Trace($"Contact Created - First Name: {firstName}, Last Name: {lastName}");
    contactDetail.name = firstName + " " + lastName;

    // Call Azure Function and Pass Contact Name
    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(ContactDetail));
    MemoryStream memoryStream = new MemoryStream();
    serializer.WriteObject(memoryStream, contactDetail);
    var jsonObject = Encoding.Default.GetString(memoryStream.ToArray());
    var webClient = new WebClient();
    webClient.Headers[HttpRequestHeader.ContentType] = "application/json";
    var code = "eAy22Izpd6kF5VTNHyArUu-I86MkbpVWOJYG9k8M-3L1AzFuGBtDxA==";
    var serviceUrl = "https://sume4functionapp.azurewebsites.net/api/SumeFunction1?code=" + code;
    string response = webClient.UploadString(serviceUrl, jsonObject);

    // Set the retrurned value (Financial system bymber) back to Contact record
    ctx.Trace($"response {response}");
    if (response != null)
        target.Attributes["so_financialsystemid"] = response;
    else
        throw new InvalidPluginExecutionException("Failed registering to FS via Azure Fuction");
}
        public class ContactDetail
        {
            public string name { get; set; }
        }

How it works

Now create Contacts and see how Financial System Id is being populated.


We can monitor this in two places of Azure.

1) Under Invocation of Azure Function as below.     


2) Under Log Stream of Function App. 


This is just a simple example, but hope this gives idea on what needs to do in each component and the sequance. 

Jun 11, 2026

Email Template to populate dynamic values from any entity

 Email Templates of Dynamics 365/ Dataverse is very useful yet its one big limitation is it only can dynamically populate values of a one Entity type. Word Document templates don't have that limitation but it is actually for generation of a document not to use in Email content. Alternatively, Word Document Templates can be used to generate a document and attach to email which is widely done.

Today we will see how to programmatically enhance the usual Email Template to have any value. Below are the steps we do.

1) When creating Email Template, introduce special tags for dynamics values we plan to populate from other entities

2) Create email with Template in Draft status.

3) Replace special tags we introduce (Template will have many other dynamic fields as usual from specific Entity type it designed to fetch data from)

4) Send the Email

Please refer Programmatically create a draft Email using Email Template (C#) for steps 2 and 4.

Lets check how code would flow with the newly introduced method. Obviously values you need to populate should be query first to replace the tags.

// Step 2: Create Draft Email
// email object is defined here

// Step 3: Replace special tags
ReplaceEmailContent(email, "{{Coordinator}}", <Value need to populate>);
ReplaceEmailContent(email, "{{ContractId}}", <Value need to populate>);

// Step 4: Send Email

// Method to call
public Entity ReplaceEmailContent(Entity email, string tagName, string tagValue)
{
    var secondValue = email.Attributes.Values.ElementAt(1);
    if (secondValue is string strValue)
    {
        var replaced = strValue.Replace(tagName, tagValue);
        var key = email.Attributes.Keys.ElementAt(1);
        email.Attributes[key] = replaced;
    }
    return email;
}

Same way, if we need to add dynamics tags to Subject of the email, that's also possible. For that, use below method.

public Entity ReplaceEmailSubject(Entity email, string tagName, string tagValue)
{
    var secondValue = email.Attributes.Values.ElementAt(0);
    if (secondValue is string strValue)
    {
        var replaced = strValue.Replace(tagName, tagValue);
        var key = email.Attributes.Keys.ElementAt(0);
        email.Attributes[key] = replaced;
    }
    return email;
}

Nov 29, 2025

Send Email to a direct address in a Flow (without Account, Contact record)

When we work with Dataverse, we use Cloud Flows/ Power Automates to send Email nowadays. Usually, we send a emails to an address associated to a Contact, Account or few other specified entity types records. How about if we need to send an email to a outside Email address which is not associated to any record. It is possible to do as below.

We need three different components here in below sequence. As explained by respective names they are to Initiate, Update and sending the Email.


1) Initiate Email

    Just initiate a Email record using Add a new row action.

2) Update Email

   Then use a Update a row action to populate below details. While passing the already initiated email to Row Id, it is needed to pass same activity Id for bind details of email.     


3) Perform a bound action

    Now its a matter of Sending the email calling SendEmail action in Perform a bound action. 

Nov 22, 2025

A way to process more than 5000 records in Cloud Flow execution

If you need to process a large number of records, for example in Dataverse, what we really do is create a scheduled Cloud Flow/ Power Automate. If the process is complex, we can encapsulate the logic in a Custom API and call from Cloud Flow. 

To fetch the records to process, you need to use List Rows operation of Dataverse Connector which returns only 5000 records as once. This is a limitation. In order to overcome this, we need to do below trick.

1) Introduce a Boolean Variable
2) Create a Do Until loop to run until this variable is False
3) Inside the Loop
    - Create List Rows operation to retrieve records
    - Set Variable to True as far as List Rows returns none zero records
4) Add a For Each control to call a Bound Operation against each record in the batch.


Caution

1) List Rows fetch should contains a specific condition for the records being fetched. (perhaps a flag)
2) Within the Custom API it is important to change this flag value once its processed either its successful or failure. 

This way, any record, once processed is omitted in next fetch resulting only one processing per a given record. Otherwise, this will go to an infinite loop which could cause issues. 

Anyway, Cloud flows can handle badly designed loops and it will anyway stop at default maximum number of loops.. still this should be avoided.

Sep 12, 2025

Attach PDF file programmatically to Email and send

Let's see how PDF file is attached to an Email and sending programmatically. Lets see why this is important.

1) Email Templates cannot be created with an attachment. (Ironically!)
2) If we attach programmatically we can change the attachment based on logic if required.

In Summery, we can initiate Email in Draft state, then attach the PDF and then send.

Initiation and sending the e-mail part is explained in Programmatically create a draft Email using Email Template (C#).

Lets see the code

// Initiate Email in Draft state

// Create Attachment
byte[] embededPdf = LoadEmbeddedPdf("PluginProject.Resources.ApplicationForm.pdf")
Guid attachmentId = CreatePdfAttchment(OrgSvc,emailId, Convert.ToBase64String(embededPdf));

// Send Email

// Methods to use
private byte[] LoadEmbeddedPdf(string resourceName)
{
    var assembly = Assembly.GetExecutingAssembly(); 
    using (Stream stream = assembly.GetManifestResourceStream(resourceName))
    {
        if (stream == null)
            throw new FileNotFoundException("Embedded PDF file not found: " + resourceName);
        using (MemoryStream ms = new MemoryStream())
        {
            stream.CopyTo(ms);
            return ms.ToArray();
        }
    }
}

public Guid CreatePdfAttchment(IOrganizationService OrgSvc, Guid emailId, string base64Pdf)
{
    Entity attachment = new Entity("activitymimeattachment");
    attachment["subject"] = "Application Form";
    attachment["filename"] = "ApplicationForm.pdf";
    attachment["mimetype"] = "application/pdf";
    attachment["body"] = base64Pdf;
    attachment["attachmentnumber"] = 1;
    attachment["objectid"] = new EntityReference("email", emailId);
    attachment["objecttypecode"] = "email";
    return OrgSvc.Create(attachment);
}

There are two important things here;

1. PDF is saved within the Project and path needs to be passed correctly in below standard.

<Project Namespace><Folder><filename>.pdf

So you will realize when I pass PluginProject.Resources.ApplicationForm.pdf, my project namespace is  PluginProject, folder name is Resources and pdf file name is ApplicationForm.pdf.

2. Go to properties of the PDF file (In VS) and do below setting.
    


Mar 29, 2025

Restore deleted Dataverse records

Microsoft has now introduced (at this writing its in Preview), a way to restore deleted record. It is mimicking  the recycle bin of windows.

Enable the Feature

First you need to enable the feature. For that got to the Settings of the environment, browse to Features and simply enabled the Recycle Bin. Here you are also allowed to enable the number of days deleted records will be kept before deleting permanently. 


In a short while feature will be ready to use.

Use Recycle Bin to restore deleted records

Now browse to Data Management and notice you got link to View Deleted Records.


Select the record(s) from resulting view and click restore to reverse the deletion.





Mar 14, 2025

Send Email with dynamic excel attachment

Sending an email with associated excel sheet with details of child records is a generic requirement and also great way to pass child record details to a customer. For example, you may need to send an email to a customer with quote details and associate quote products as a excel attachment. 

In my example I am sending email to a Account and Sender is a Queue (you may obviously use a System user). I am sending Opportunity details and associated excel will carry Opportunity Products. This Email will be shown in timeline of Opportunity hence regarding Object would be the Opportunity. 

I have two separate code snippets here.

1) Sending the Email with Template and Excel

What we need to understand is we should create the Email first and then send as two steps.. This way, we get a room prior to sending, to attach the excel. Note how we pass different Ids like Sender, Template, Receiver and Regarding Object here. Also notice that we pass the excel as the attachment body.

Public void SendEmailWithPaymentEvaluationDetails(Guid templateId, Guid toAccountId, Guid fromQueueId, Guid regOpportunityId)
{
    // Initiate Email
    InstantiateTemplateRequest request = new InstantiateTemplateRequest()
    {
        TemplateId = new Guid(templateId),
        ObjectId = invoiceRequest.Id,
        ObjectType = invoiceRequest.LogicalName
    };
    InstantiateTemplateResponse response = (InstantiateTemplateResponse)OrgService.Execute(request);
    Entity email = response.EntityCollection[0];
    Entity Fromparty = new Entity("activityparty");
    Entity Toparty = new Entity("activityparty");
    Toparty["partyid"] = new EntityReference("account", toAccountId);
    Fromparty["partyid"] = new EntityReference("queue", fromQueueId);
    email["from"] = new Entity[] { Fromparty };
    email["to"] = new Entity[] { Toparty };
    email["directioncode"] = true;
    email["regardingobjectid"] = new EntityReference("opportunity", regOpportunityId);
    Guid emailId = OrgService.Create(email);

    // Link the Attachment
    Entity attachment = new Entity("activitymimeattachment");
    attachment["subject"] = "OpportunityId Product List";
    attachment["filename"] = "OpportunityId Product List.xlsx";
    attachment["body"] = Convert.ToBase64String(CompileExcelFile(regOpportunityId));
    attachment["mimetype"] = "application/vnd.ms-excel";
    attachment["attachmentnumber"] = 1;
    attachment["objectid"] = new EntityReference(email.LogicalName, emailId);
    attachment["objecttypecode"] = email.LogicalName;
    OrgService.Create(attachment);

    // Send Email
    SendEmailRequest sendEmailRequest = new SendEmailRequest
    {
        EmailId = emailId,
        TrackingToken = string.Empty,
        IssueSend = true
    };
    SendEmailResponse sendEmailResponse = (SendEmailResponse)OrgService.Execute(sendEmailRequest);
}

2) Compilation of Excel

Here we compile the excel which is called in above method when preparing the attachment. 
In this technique, we need to have a view created in Opportunity Product and retrieve its Id to be used here. That's the Id you see in SavedQuery. Interestingly, though we assign an id of a saved view, we are defining dynamically what we need in the excel via our own Fetch query. Under grid section, we adjust the column widths etc.
 
public byte[] CompileExcelFile(Guid regOpportunityId)
{
    var exportToExcelRequest = new OrganizationRequest("ExportToExcel");
    exportToExcelRequest.Parameters = new ParameterCollection();
    exportToExcelRequest.Parameters.Add(new KeyValuePair<string, object>("View", new EntityReference("savedquery", new Guid("{4c523f5b-e8c5-4cb5-bc83-bf4ef934342d}"))));
    string stringFetchXml = @"<fetch distinct='false' no-lock='false' mapping='logical' returntotalrecordcount='true'>
                                <entity name='opportunityproduct'>
                                    <attribute name='lineitemnumber' />
                                    <attribute name='productname' />
                                    <attribute name='description' />
                                    <attribute name='baseamount' />
                                    <filter>
                                           <condition attribute='opportunityid' operator='eq' value='{0}' />
                                    </filter>
                                   </entity>
                            </fetch>";
    exportToExcelRequest.Parameters.Add(new KeyValuePair<string, object>("FetchXml", String.Format(stringFetchXml, regOpportunityId.ToString())));
    exportToExcelRequest.Parameters.Add(new KeyValuePair<string, object>("LayoutXml", @"
            <grid name='resultset' object='2' jump='lineitemnumber' select='1' icon='1' preview='1'>
                <row name='result' id='opportunityproductid'>
                    <cell name='lineitemnumber' width='100' />
                    <cell name='productname' width='200' />
                    <cell name='description' width='300' />
                    <cell name='baseamount' width='125' />
                </row>
            </grid>"));
    exportToExcelRequest.Parameters.Add(new KeyValuePair<string, object>("QueryApi", ""));
    exportToExcelRequest.Parameters.Add(new KeyValuePair<string, object>("QueryParameters", new InputArgumentCollection()));
    var exportToExcelResponse = OrgService.Execute(exportToExcelRequest);
    if (exportToExcelResponse.Results.Any())
        return exportToExcelResponse.Results["ExcelFile"] as byte[];
    else
        return null;
}

Hope this helps!

Feb 14, 2025

Programmatically create a draft Email using Email Template (C#)

Previously we discussed how to send an Email using a Email Template, but we noticed it just sends the email but no chance of create and save as a draft. In some instances we need to create the Draft email to be sent later after checking or/and modifications by the user. 

In such situations we can use below code. One can say its simply possible to use CREATE message of the Org service to achieve this but it is not possible to use a Template which is a constrain. 

By creating the draft first, it allows you to programmatically or manually attach attachments prior to sending the email.

Here InstantiateTemplateRequest  message does the magic.

 public void CreateDraftEmailToPrimaryContactOfAccount(Account account)
 {
     InstantiateTemplateRequest request = new InstantiateTemplateRequest()
     {
         TemplateId = new Guid("bf0b97c7-d5a3-4a3f-8771-a1cd737ab555"),
         ObjectId = account.Id,
         ObjectType = Account.LogicalName
     };
     InstantiateTemplateResponse response = (InstantiateTemplateResponse)OrgService.Execute(request);

     Entity email = response.EntityCollection[0];
     Entity Fromparty = new Entity("activityparty");
     Entity Toparty = new Entity("activityparty");
     Toparty["partyid"] = new EntityReference(Account.EntityLogicalName, account.PrimaryContactId.Id);
     Fromparty["partyid"] = new EntityReference("queue", new Guid("f14a45e9-fac5-4ba0-9a95-c07fe1adabf0"));
     email["from"] = new Entity[] { Fromparty };
     email["to"] = new Entity[] { Toparty };
     email["directioncode"] = true;
     email["regardingobjectid"] = new EntityReference(Account.EntityLogicalName, account.Id);
     Guid emailId = OrgService.Create(email);
}

When ready if you need to send the Email programmatically, below SendEmailRequest message can be used as below.

SendEmailRequest sendEmailRequest = new SendEmailRequest
{
     EmailId = emailId,
     TrackingToken = string.Empty,
     IssueSend = true
};
SendEmailResponse sendEmailResponse = (SendEmailResponse)OrgService.Execute(sendEmailRequest);

Related Posts
Programmatically send Email with Template (c#)

Programmatically send Email with Template (c#)

This is a code snippet that sends Email programmatically (in C#) while using an Email Template

Explained scenario, we send an Email to Primary Contact of the Account. We set Account as the regarding object of the Email so this Email activity will associate with Account and will be displayed in Account's timeline. Also we have to pass Account as the regarding object of Template since we want dynamic fields of Template to be filled with Account field values as necessary.

Actually SendEmailFromTemplateRequest message does the magic.

public void SendEmailToPrimaryContactOfAccount(Account account)
{
    Entity Fromparty = new Entity("activityparty");
    Entity Toparty = new Entity("activityparty");
    Toparty["partyid"] = new EntityReference(Contact.EntityLogicalName, account.PrimaryContactId.Id);
    Fromparty["partyid"] = new EntityReference("queue", new Guid("f14a45e9-fac5-4ba0-9a95-c07fe1adabf0"));
    Entity email = new Entity("email");
    email["from"] = new Entity[] { Fromparty };
    email["to"] = new Entity[] { Toparty };
    email["directioncode"] = true;
    email["regardingobjectid"] = new EntityReference(Account.EntityLogicalName, account.Id);

    SendEmailFromTemplateRequest emailUsingTemplateReq = new SendEmailFromTemplateRequest
    {
        Target = email,
        TemplateId = new Guid("bf0b97c7-d5a3-4a3f-8771-a1cd737ab555"),
        RegardingId = account.Id,
        RegardingType = Account.EntityLogicalName
    };
    var emailUsingTemplateRes = OrgService.Execute(emailUsingTemplateReq);
} 

Please note I am sending this email from a queue record. Obviously you can send from a system users as well. In such case, from activity party has to be changed accordingly.

One thing to note is, this method just sends the email, so you are not save Email in draft status.

Related Posts
Programmatically create a draft Email using Email Template (C#)

Feb 8, 2025

Very useful Formula field

Formula fields are pretty useful type in my opinion. It helps us define some values in a field using existing values, but defining them as we want. 

How to do:

Start just like you create any other field, and select Formula within the type selection.


Then intelligence will help you build your own formula. Start clicking Ctrl and Space bar to start with existing field.


Example

Suppose I have below status codes in Contact entity. 



If we need to pass instruction based on the values, we can use below Formula field to be used in Email.

Switch('Status Reason',
  Blank(), "",
 'Status Reason (Contacts)'.Inactive,"Redirect to Sales Team",
 'Status Reason (Contacts)'.'Not Verified',"Seek Approval from Manager",
 'Status Reason (Contacts)'.Verified,"Ready send Stater Pack"
)

This is just a one simple example. 

References;

Aug 21, 2024

A big loophole in field level security !

We all use field level security as a trustworthy way of hiding selected fields from an entity where user could have the access rights for remaining fields. 

Typical scenario could be, Contact entity is a very generic type yet you could have sensitive details such as salary, bank details or marital status etc. Here field level security come in handy since you can hide only those fields for selected users.

Loophole

Well..keep in mind if users are allowed to check audit history of the record, irrespective of field level security setting, user will see all the audit details of all the fields those are enabled for auditing. This is not ideal isn't it?  :-( 

Jun 4, 2024

Hide New Look switch

Dataverse header shows a button to switch to New look as below.


Sometimes organizations would decide to hide this button due to various reasons. Basically, some users who tried this will get the new experience but organization may not be ready yet. For example, guides/ manually may not resemble this new look.

Last time when this was requested, we managed to hide the switch as per steps explained in below article. https://www.powercommunity.com/disabling-try-the-new-look-switch-in-power-apps/

Anyway, its different now and much easier. Follow below steps;

1. Browse to https://admin.powerplatform.microsoft.com/environments and select correct Environment

2. Then click Apps and select the correct App and click edit 

3. Then Click Settings in the top 

4. Click the Features

5. Go to Try the new look button and switch it off.

May 17, 2024

Execute Multiple

In some cases we need to repeat the same operation. It may be creating a collection of records or updating a collection or records. We are good to do those via available CRUD operations of the Organization Service.

However if we do a collection within a loop, we should understand we repeat the same operation that result number of server calls which is not sufficient. Particularly, if you need to do this within a synchronous process it important to complete quickly rather keeping the user waiting.

In such situations, we would do execute multiple operations. Lets check the code snippet.

var executeMultipleRequest = new ExecuteMultipleRequest
{
    Settings = new ExecuteMultipleSettings { ContinueOnError = true, ReturnResponses = false },
    Requests = new OrganizationRequestCollection()
};

for (int i = 0; i < 5; i++)
{
    var paymentevaluation = new Entity("contact")
    {
        ["firstname"] = $"Test First Name {i}",
        ["lastname"] = $"Test Last Name {i}",
    };

    executeMultipleRequest.Requests.Add(new CreateRequest { Target = paymentevaluation });
}

var data = (ExecuteMultipleResponse)service.Execute(executeMultipleRequest);

foreach (var response in data.Responses)
{
    Console.WriteLine($"{response.RequestIndex}: {response.Fault}..");
}
Notice that we add all the entities to be created and execute once in this code. This is significantly faster than going through a loop.
Notes
> Keep in mind, maximum number of requests can be added to a execution is 1000.
> This also had a limitation of 2 concurrent operations, but now its removed.

May 11, 2024

ConditionOperator "Contains" doesnt work

When retrieving data using RetrieveMultiple we use different condition operators apart from Equal which is the most used one. 

Anyway, I noticed Contains operator is not working. For example below code, though looks alright, will not work. Its disappoint error message is not helpful either.

   
var query = new QueryExpression("account")
{
    ColumnSet = new ColumnSet("accountid", "name"),
    Criteria = new FilterExpression(LogicalOperator.And),
    TopCount = 10
};
query.Criteria.AddCondition("so_groupname", ConditionOperator.Contains, "expolanka");
Solution is to you like key work instead of Contains which does the same. Anyway, one thing to keep in mind is you need to use % mark for the task your check for. Check below;
   
query.Criteria.AddCondition("so_groupname", ConditionOperator.Like, "%expolanka%");

Nov 4, 2023

Check if deployed assembly got your code

While we have all the processes in place for deployments, I still sometimes feel like checking if my code change was actually deployed. This happens when we work with many developers at the same time where anyone can deploy a new version of assembly to DEV environment. What is in the DEV at the time of the deployment will be pushed to other environments. Here we explain a way to decompile and check the assembly using two tools.

A. Download the Assembly using Assembly Recovery Tool (Xrm Toolbox)

Once we connect to an environment and load the tool, it list down all the assemblies of the environment.



Then its a matter of selecting the correct assembly and download.


B. Decompile the code using JetBrains DotPeak (https://www.jetbrains.com/decompiler/)

Download and install the JetBrains DotPeak tool in your PC/ Laptop.

Then you are able to open the folder where you saved the Assembly in the previous step where you can go down to classes and identify the method you are interested in. Then double click it and you will get the code in right hand side pane.


Hope this helps.

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.