Category Archives: D365 Project Service Automation
Plugin Class Code Recovery using XRMToolBox & C# DotPeek.
In an ideal Dynamics 365 (Dataverse) project, plugin source code lives safely in a version-controlled repository, flows cleanly through Azure DevOps pipelines, and is always recoverable. In reality, many of us inherit environments where that discipline didn’t exist. I recently worked with a customer where: This created a common but uncomfortable challenge in the Dynamics 365 world:How do you maintain, debug, or enhance plugins when the source code is lost? Rewriting everything from scratch was risky and time-consuming. Guessing behavior based on runtime results wasn’t reliable. Fortunately, Dynamics 365 and the .NET ecosystem give us a practical and effective alternative. Using XrmToolBox and JetBrains dotPeek, it is possible to recover readable C# plugin code directly from the deployed assembly. (Though the C# Class code recovered won’t be 100% exact, as the variable names would be different and generic; it is only suitable for close logic, structure & functional recovery) The Practical Solution The approach consists of two main steps: This does not magically restore comments or original formatting, but it does give a working, understandable code that closely reflects the original plugin logic. Tools Used Step 1: Extract the Plugin Assembly from Dataverse 1. Connect to the Environment 2. Load the Assembly Recovery Tool 3. Download the DLL At this point, you have successfully recovered the compiled plugin assembly exactly as it exists in the environment. Step 2: Decompile the DLL Using JetBrains dotPeek 1. Open dotPeek 2. Explore the Decompiled Code dotPeek will: One can now browse through: This is usually more than enough to understand how the plugin works. 3. Export to a Visual Studio Project (Optional but Recommended) One of dotPeek’s most powerful features is Export to Project: This gives you a proper .csproj with class files that you can open, build, and extend. Possibilities with the Recovered Code Once you have the decompiled C# code, several options open up: 1. Rebuild the Plugin Assembly 2. Re-register the Plugin 3. Maintain or Enhance Functionality Important Considerations Key Takeaway Losing plugin source code does not mean losing control of your Dynamics 365 solution. With XrmToolBox’s Assembly Recovery Tool and JetBrains dotPeek, you can: There are chances while working in Dynamics 365 technologies, that a developer might face this situation. Knowing this technique can save days-or weeks-of effort and give your customer confidence that their system remains fully supportable. We hope you found this blog useful, and if you would like to discuss anything, you can reach out to us at transform@cloudfronts.com
Share Story :
Browser-Level State Retention in Dynamics 365 CRM: Improving Performance & UX with Session Storage
Dynamics 365 model-driven apps are excellent at storing business data, but not every piece of information belongs in Dataverse. A common design folly is using Dataverse fields to store temporary UI state-things like selected views, filters, or user navigation preferences. While this works technically, it introduces unnecessary performance overhead and can create incorrect behavior in multi-user environments. In this blog, I’ll focus on browser-level retention of CRM UI data using “sessionStorage“, using subgrid view retention as a practical example for a technology consulting and cybersecurity services firm based in Houston, Texas, USA, specializing in modern digital transformation and enterprise security solutions. The Real Problem: UI State vs Business Data Let’s separate concerns clearly: Type Example Where it should live Business data Status, owner, amounts Dataverse UI state Selected view, filter, scroll position Browser Subgrid views fall squarely into the UI state category. Scenario: Subgrid View Resetting on Navigation Users reported the following behavior: This breaks user workflow, especially for records that users revisit frequently. Possible Solution: Persisting UI State in Dataverse (Original Approach) This would attempt to fix it by storing the selected subgrid view GUID in a Dataverse field on the parent record. How It Works Why this might look reasonable The Hidden Problems 1] Slower Form Execution 2] Data Model Pollution 3] Incorrect Multi-User Behavior 4] Scalability Issues In short, Dataverse was doing work it should never have been asked to do. Workaround to this Approach: Keep UI State in the Browser for that session, But practically: The selected subgrid view belongs to the user’s session, not the record. Once that boundary is respected, the solution becomes much cleaner. Practical Solution: Browser Session Storage (Improved Approach) Instead of persisting view selection in Dataverse, we store it locally in the browser using sessionStorage. sessionStorage is part of the Web Storage API, which provides a way to store key-value pairs in a web browser. Unlike localStorage, which persists data even after the browser is closed, sessionStorage is designed to store data only for the duration of a single session. This means that the data is available as long as the tab or window is open, and it is cleared when the tab or window is closed. Why Session Storage? How the Improved Solution Works 1. Store the View Locally on Subgrid Change 2. Restore the View on Form/Grid Load This ensures that when the user revisits the form, the subgrid opens exactly where they left off. Why This Approach Is Superior 1] Faster Execution 2] Correct User Experience 3] Clean Architecture 4] Zero Backend Impact When to Use Browser-Level Retention Use this pattern when: Examples: To conclude, not all data deserves to live in Dataverse. When you store UI state in the browser instead of the database, you gain: Subgrid view retention is just one example-but the principle applies broadly across Dynamics 365 customizations. We hope you found this blog useful, and if you would like to discuss anything, you can reach out to us at transform@cloudfronts.com
Share Story :
Exposing Plugins as Bound Actions for Power Automate Flows: A Practical Procedure for Efficient Record Processing, involving several records.
In complex business processes, like calculating commissions or validating data across multiple records, applying the same logic repeatedly in a Power Automate flow can quickly become inefficient and difficult to maintain. A more scalable approach is to encapsulate the logic in a Dataverse plugin, expose it as a bound action, and then call this action from a flow. This method centralizes business rules, reduces redundancy, and improves maintainability. In this post, we’ll walk through the steps to implement this approach and examine its advantages over applying the same logic directly within a flow for each individual record. We’ll illustrate this with a practical example from a Houston-based technology consulting and cybersecurity services firm that specializes in modern digital transformation and enterprise security solutions. Flow Diagram Step 1: Create the PluginThe first step is to write a plugin that contains the logic you want to apply to each record. Example: DuplicateCommissionsCounter Step 2: Expose the Plugin as a Bound ActionInstead of running plugin logic manually for each record, you can register it as a bound action in Dataverse. Procedure: E.g. 2. Attach your plugin to this action. Outcome: This exposes your plugin logic as a reusable, callable bound action. Any process or flow can now invoke it for a specific invoice record. Step 3: Use Power Automate to Call the Bound ActionOnce the plugin is exposed, you can loop through multiple records in a flow and call the action. Procedure in Power Automate: This approach ensures that all complex logic resides in the plugin, while the flow orchestrates which records need processing. Advantages Over Logic Directly in the Flow To conclude, exposing plugins as bound actions is a robust, maintainable way to apply complex logic across multiple records in Dataverse. It allows Power Automate flows to focus on orchestration rather than logic execution, leading to cleaner, faster, and easier-to-manage solutions. We hope you found this blog useful, and if you would like to discuss anything, you can reach out to us at transform@cloudfronts.com
Share Story :
How to Display the ‘+New’ Quote Button Only for System Administrators Using JavaScript and Ribbon Workbench in Dynamics 365 CRM
Uploading and managing quotes efficiently is crucial for Dynamics 365 CRM users. However, sometimes you may want to restrict certain buttons, such as the ‘+New’ Quote button, to only users with specific roles, like the “System Administrator.” In this guide, I’ll walk you through how to achieve this by leveraging JavaScript and the Ribbon Workbench tool in Dynamics 365. This method allows administrators to control button visibility based on user roles, ensuring that only users with the correct permissions can access sensitive functionality. The Use-Case: Restricting Access to the ‘+New’ Quote Button for Non-Administrators. Imagine a scenario where your organization needs to ensure that only users with a “System Administrator” role can create new quotes in Dynamics 365. This is crucial for maintaining control over who can initiate important processes within your CRM system. Using JavaScript and Ribbon Workbench, you can easily customize the UI to hide the ‘+New’ Quote button for non-administrators. Here’s how this use case can be implemented: In this scenario, your team wants to ensure that only system administrators have access to the “+New” button for creating quotes in the system. For non-administrators, the button will be hidden from both the homepage subgrid and the main quote tab to prevent unauthorized users from creating quotes. By using the Ribbon Workbench tool, a custom JavaScript function is created to check if a user has the “System Administrator” role. If they do, the “+New” button remains visible, and they can create a new quote. For all other users, the button is hidden. Key Components of the Solution 1. Ribbon Workbench: The Ribbon Workbench tool allows you to customize the Dynamics 365 ribbon, enabling you to create custom buttons and define their visibility and actions. It is used to create the new custom “+New” Quote button, which replaces the default button while maintaining system integrity. 2. JavaScript Customization: Custom JavaScript is used to manage role-based access for the “+New” Quote button. The script checks the user’s role within Dynamics 365 to ensure that only users with the “System Administrator” role can view and use the button. This helps enforce security and restricts unauthorized users from creating new quotes. 3. Enable Rule for Button Visibility: An Enable Rule is set to control the visibility of the custom “+New” Quote button based on the user’s role. It ensures that only users with the “System Administrator” role can see and use the button, while hiding it for other users. 4. Custom Button Action (Command): The command linked to the custom “+New” button triggers a custom action (JavaScript function) to open the quote form. This ensures that the action associated with the button aligns with the business needs and provides a seamless user experience for administrators. Step-by-Step Process Sign in to Dynamics 365 using your URL, such as abc.dynamics.com, and enter your credentials or login to make.powerapps.com Create a solution and add the web resource. Once it’s done login to ribbon workbench from XRM toolbox and connect to your organization. After logging in, it is recommended to create a new solution for Ribbon Workbench in Dynamics 365. Ensure that no forms, views, charts, or other entities are included, as Ribbon Workbench may fail to upload the solution with excessive data. Only include the Quote entity with no additional dependencies. Ensure the existing +New Quote button is hidden, as modifying Microsoft-standard buttons is not recommended. Instead, create a new custom button and implement the functionality for creating a new quote Form using custom JavaScript. I have provided the code for this functionality as well. Ensure that the existing +New button for quote would be hidden from the homepage Subgrid and the quotes main tab. Next step would be to create a enable rule. Enable rule is used to control the visibility and availability of a button or command of the button. Name the id of your choice but make sure to add the suffix Enable Rule. Here, un-customised is set to False. By setting isCore (or Un customized) to false, you’re indicating that the button or element is a custom component, not part of the out-of-the-box (core) solution provided by Microsoft. This helps differentiate custom actions from the default ones in the system. Below is the code for the new quote form create and user role-based code. Make sure to select the Function name properly. After setting the enable rule, go to the Commands section in Ribbon Workbench and rename the command. A command defines the action triggered by a button click. Since this is a new button, you’ll need to add the custom form opening code. Below is the function for creating the form. Final Steps: Once the command is added, don’t forget to add the Enable rule that you have created above. Once the command is added, make sure to add all the rules we wrote into the custom button. The image also needs to be added so that the icon can be visible. My custom +New icon looks like this. Testing: Once everything is done, make sure Publish the changes. You can now try to log in from the user that has no System administrator role. Once logged in, you can see that button is not visible. Button will be only visible to user that have system Administrator role. User having no System Administrator role. You can see below that there’s no +New button displayed. To conclude, by following this guide, you can efficiently control the visibility of the ‘+New’ Quote button in Dynamics 365 CRM, making it accessible only to users with the “System Administrator” role. This ensures better control over who can create quotes in the system while maintaining the flexibility of user roles. We hope you found this blog useful, and if you would like to discuss anything, you can reach out to us at transform@cloudfonts.com.
Share Story :
Disable field on change of tab in D365 CE
Use case – Our requirement is to enable field description field on invoice line form on clicking of tab General. Let’s see how we can achieve this Solution – Step 1 – Create web resource with below function- var invoiceLineCustomization = { unlockField : function(executionContext) { var formContext = executionContext.getFormContext(); formContext.getControl(“description”).setDisabled(false); }, } Step 2: Add this web resource on tab property event TabStateChange and try. (path to go to event tab – Click on tab -> change properties -> event) Output – Hope this helps !
Share Story :
Send an Email to all users in a D365 Team using power automate.
D365 gives us a functionality to assign a record to a group of users which can be archived by using a D365 Team these users then are know as members of that respective team, due to functionality restrictions we cannot send an email to a D365 team, however there are a few workarounds by which we can achieve this functionality. Lets consider a case. Suppose we have a D365 team called as “Accounts Associates” we have added a set of users in this team. Now if an invoice milestone is in the ready state i.e. “Ready For Invoicing” we need to send a reminder email to this “Accounts Associates” team to take an action regarding the ready invoicing. Solution :- The following case can be achieved by using an Out of the box functionality i.e. By using a distribution list Note :- (we must have an Microsoft Exchange License). Lets Begin with the implementation. Step – 1 Creating a Distribution List Login to your admin center (Link –https://admin.microsoft.com/) In the Admin center Section of the Left navigation bar select “Exchange”. Under the “recipients” select “groups”. In the “+ New Microsoft 365 Group” pull down the dropdown and add the distribution list. Add the Display name and the “Alias” and save the Distribution list. Add same users which are present in the teams to this Distribution list. Step – 2 Creating a Queue in D365 Go to “Settings” -> “Service Management” ->” Queues” and click on “+NEW” -> give it a name -> “Save” A mailbox would be created with the same name that of the queue. Open the mailbox. The Email address field will be blank, add the Distribution List’s email address created in Step 1. Step -3 Create a New Team or select an Existing Team. In the Default Queue lookup, select the Queue created in Step 2. Step – 4 Create a Flow which triggers on update of a project contract line milestone i.e. When status is ready for invoicing Flow triggers when Project Contract Line is Updated, Condition Invoice Milestone is Ready for invoicing for which click on the “…” select settings and add the following condition in the trigger sectio Get the Teams ID in this case I have hardcoded the ID as no record was associated with it to retrieve it Get the Teams Details. Get the Default Queue to which the email will be triggered . Send an Email to the Incoming Email of that Queue which is Email ID set on the Distribution list. Note : (We will have to Manually add or remove the users from both the Distribution list and the Teams. i.e. both the team and the distribution list must be sync, if a member is added or removed from the team the same should be done in the distribution list ) Output . Hope this helps.!
Share Story :
How to bring in Project Task field from Resource Requirements to Time Entries if imported via, Bookings.
Import Bookings is one of the important features provided by PSA for users to do Time Entries quickly and efficiently. An issue faced while using this functionality is the Project Tasks are not imported with the Bookings Records (As Shown in the Image Below). A solution to this issue is two automated flows: To Bring the Project Tasks from Resource Requirements Entity to Bookable Resource Booking. Hence to bring the obtained Project Tasks from Bookable Resource Booking to Time Entries. Let’s Begin with the Implementation of the solution! (Flow To get Project Tasks from Resource Requirements to Bookable Resource Bookings) Step: 1 Bringing Project Tasks from Resource Requirement’s to Bookable Resource Booking. Step: 2 Update the Bookable Recourse Booking Record with the obtained project task. Now we have successfully obtained the Project task in the Bookable Recourse Bookings Entity from the Resource Requirements, Our Next step is to Take this Project task on the Time Entries. (Flow to get Project Task from Bookable Resource Bookings to Time Entries) Step: 1 Bringing Project Task from Bookable Resource bookings to Time Entries. (Tip : It is better to check if the Project Task Field is empty or not hence we can also put a condition to do so, if the Project Task Field is empty proceed with updating the Project Task field else Terminate.) Step: 2 Get the Project Task from the Bookable Recourse Bookings. Step: 3 Update the Time Entries with the obtained Project task. Step: 4 Import Bookings and there you go you will now be able to see the Project Tasks. Hope this Helps!
Share Story :
How to Post the Fixed Bid and Time and Material based invoice in F&O in Project Operations
In my previous blog referred here https://d365feeds.com/2020/07/08/how-do-contract-milestones-and-projects-flow-between-d365-ce-to-fo-in-project-operations/, we saw how the contract and milestones flow between CE and F&O in the integrated scenario in Project Operations. Next step is to Post the Milestones or the Approved Time entries (in case of T&M based projects) in F&O (Finance and Operations) Let’s looks at first Milestone based Invoice posting in F&O for a Fixed Bid Project: PN: How to log in to the environment is shown in my previous blog in the link above. Step 1: Login to the CE Environment to the Milestone that you need to Invoice and flip the status to “Ready for invoicing”. Step 2: The invoice is created in the CE Environment and you need to confirm the same. Upon confirming the invoice it gets integrated to the F&O Environment. Step 3: Navigate to F&O Environment and go to Project Management and Accounting à Import from staging table. This will import all the transactions available in the staging area to F&O environment. Step 4: At this juncture the Invoice is now posted to the F&O Environment. To check the same in F&O environment navigate to Project Management and Accounting Module à Pending project transactions You can see the Invoices milestone below. Step 5: Select the invoice and click on Post. This is when the invoicing of milestone is completed. This step is recommended to be performed by the Accounts Manager. Now we shall see how to Invoice Time and Material projects. Follow the steps to accomplish the same. Step 1: Navigate to CE Environment and get some time entries done on the T&M project as shown below. Step 2: Submit the time entries done by clicking the Submit button as shown below. The status of the time entries changes to Submitted from Draft status. Step 3: The project manager will now have to approve the time entries submitted from the Approvals tab. Step 4: As soon as the time entries are approved they are integrated and reside in the staging area of F&O. You then need to Import all the time entries from the staging area. Navigate to F&O Environment and go to Project Management and Accounting à Import from staging table. This will import all the transactions available in the staging area to F&O environment. Step 5: Post that navigate to Project Management and Accounting à Project Operation integration journal where all the approved time entries in CE environment get collected. Please understand that if there is an active Journal existing in F&O environment, then all the approved time entries for all the projects will be integrated to the same Journal, unless all the entries in that integration journal is approved. Step 6: Select the Journal from the below and click on the Post button from Ribbon. This will post all the transactions from the Journal, which also the final step that the Accounts manager will perform to do the invoicing. Above methods when performed can ensure that the milestones and the time entries for FP and T&M projects respectively are done. The above operations are prescribed to be done by the Accounts Manager in the company. This ends the process of Posting the Invoice in F&O Environment. The above blog is written with the best possible knowledge of Project Operations and practical experience.
Share Story :
Connect D365 CRM CDS Database from SQL Server
Many times, we feel like why I can’t access D365 CRM Database directly from MS SQL Server, so here is my blog that will guide you on how you can connect D365 CRM CDS Database using MS SQL Server Steps to enable D365 CRM CDS Database to make it connect from MS SQL Server: Login to https://admin.powerplatform.microsoft.com/ using administrator credentials. In Environment section, click on your environment for which you want to enable D365 CRM CDS for MS SQL Server. (In my case I am clicking on DemoEnvironment as shown below.) When Environment opens click on settings in header. Settings page will open, Click on Product and then click on Features. When features Page opens enable TDS Endpoint (Preview) and click save. Now, we have successfully enabled D365 CRM CDS to connect it from MS SQL Server. Steps to Connect CDS Database from MS SQL Server: Open MS SQL Server. In connect to SQL Server Window enter Server name (It will be your D365 CRM URL) followed by comma and Port Number (5558) e.g. of server name yourdomain.crm.dynamics.com,5558. Select Authentication as Azure Active Directory – Password. Enter Username: Your admin user id e.g. admin@xyz.com Enter Password: (Your Login password) ******** Click Connect. Now, you have successfully connected to D365 CRM DB. Write a select query and test if it’s working.
Share Story :
Bill on Time, Get Paid on Time – Importance of the AR Report for a Professional Services Organization
In my last LinkedIn Post (Cash Position Report), I talked about the strategic importance of Cash on hand for a Professional Services Organization. In this post, I want to talk about the importance of the Overdue Accounts Receivable (AR) Report. As a Professional Services firm, most of our revenue comes from Project based delivery of Services. We have some top-line revenue from the subscription services we sell like Dynamics 365, but it’s not significant. So, our primary source of revenue is Services. We needed to ensure we bill on time, get paid on time. So we developed our Power BI AR Report as shown below – So let’s dive in! A few things to note in the above Report – It is a PowerBI Report embedded in our Leadership Team in our Microsoft Teams platform. We call it the PSA AR Report, as the reporting comes from our invoicing in Dynamics 365 PSA. Dynamics 365 PSA is our ‘single source of truth‘ for all our Project based billing. The bottom of the Report has two tabs – Services and Licensing/Commission Invoices. More on that shortly. Dynamics 365 PSA is our the single source of truth for all Customer Invoicing. We run all our Project based Services Invoicing from the Invoicing and Contract Milestone Schedule in Dynamics 365 PSA. This means our Allocations, Contract Milestones and our Time entries are always up-to-date, otherwise our invoicing schedule would be incorrect. This ensures good Project Management practices. Now PSA does not handle taxation, so you have to either setup your taxation customization or use an off the shelf tax add on that is available on the Microsoft AppSource. If none of these options are possible, then you can decide to create your invoices in your Accounting system and integrate those into Dynamics 365 PSA. We do that for our Licensing invoices to our Customers and integrate those from our QuickBooks Online Accounting system into Dynamics 365 PSA. We also ensure that invoices are only emailed to customers from Dynamics 365 so we can track these emails. Further, we update Invoice Statuses from Draft to Sent to Paid. Now let’s get into the Report. Basically, we have color coded our Report based on the following simple rules – Red for anything that is overdue by 30 days or more, yellow for anything that is between 1-30 days overdue and no color coding for current invoices. The visual impact of color coding can’t be emphasized enough. On the top left corner of the Report, we have an option to search by Customer, so we can quickly get all invoices for a specific customer in the AR Report. This becomes very useful when you want to just share a snapshot with your customer for overdue invoices. Handling Multiple Legal Entities: We have three legal entities – India, USA and Singapore. We have three separate QuickBooks Online Accounts for each legal entity, but we use a single Dynamics 365 CRM platform. We have made customizations on our Invoice entity to ensure we capture the correct legal entity. In the example below, you can see we classify our Invoices by legal entity in our Report – You can see there is column called ‘link’ in the above reports. Clicking on any invoice in this link directly takes us to the Invoice record in Dynamics 365. Overdue Reminders Alerts- We automated the Overdue Reminders so that our system automatically sends out a reminder for all overdue invoices every Monday. After all this effort, you still need to ensure regular and rigorous review of this report to ensure you can take action on overdue invoices. This is done through our scheduled Monday morning Management Status Meetings. The agenda for this meeting is recurring and hence set in advance, but this Management meeting always starts with AR Report Review. Our Accounts Manager is invited for the first 15 minutes and we go through all Overdue Invoices (especially the Red color coded ones!) and decide if we need to take further steps like setting up a meeting with the customer. If you are a small or mid sized Services organization, it is of utmost importance to get paid on time. By ensuring you have such a report and reviewing and planning action items for overdue invoices, you will run an efficient Services organization. In addition, there is another strategic benefit here – this report is like a Quality Check on your services. If your customer is paying on time and suddenly does not, your proactive action to talk with the customer can help you understand if there are any issues in your Services and you can take corrective action. Our PSA AR Report is available to our Management team (this includes our Delivery Heads and Practice Leads as well) through Microsoft Teams and they can view it any time they want, planning action items as needed. If it is hidden away only with the Accounts Team and available through some weekly PDF report, it is not efficient for your organization. This Report will help your organization achieve it’s Objective – ‘bill on time, get paid on time.’ If you are keen on understanding more about our Internal Systems that keep us running and growing, our Internal Systems page is a wonderful resource – https://www.cloudfronts.com/our-internal-systems/ or reach out to me at ashah@cloudfronts.com.
