Sunday, September 27, 2020

D365 CE Mobile Tips: Capturing image using D365 Mobile

 Microsoft provides a set of client APIs which can use to implement device-specific functionalities in D365 Mobile. Those client APIs provide device-specific functionalities like Capture Audio, Capture Image, Capture Video, Scanning Barcodes, Get Geo Position, and Upload Media File. Since D365 Mobile available on almost all major mobile platforms accessing device-specific functions may require native mobile programming. However, if developers use Microsoft provided client APIs then they can get rid of device-specific programming and implement device specific functionalities in Unified Interface with help of Microsoft XRM Client. For more details about XRM.Device APIs please refer to MSDN article.

 https://docs.microsoft.com/en-us/powerapps/developer/model-driven-apps/clientapi/reference/xrm-device

 In this blog post will discuss how to use “Xrm.Device.captureImage” APIto capture images from the mobile devices and attached them as an annotation.

There are few image options that can set before capturing an image.

  • allowEdit– If this flag set to yes then the user can edit the image before confirming it. We experienced some issues in Android and will mention them below                
  • height– This will allow users to crop the image after its taken                
  • width –same as the height, the user can crop the captured image.
  • preferFrontCamera– if this flag set to yes then the system will switch to the front camera to capture image                
  • quality– this is a percentage that controls the quality of the image. Value should between0 to 100.

Following code will trigger as a result of button click in custom HTML file added as web resource in Unified Interface form.

function CaptureImage(event) {
    var parentRecordId = event.currentTarget.id;
    var fileName = parentRecordId + ":" + new Date().toLocaleString();
    var Client = globalContext.client.getClient();
    if (Client.toLocaleLowerCase() == "mobile") {
        var imgOptions = {};
        imgOptions.allowEdit = false;
        imgOptions.height = ImageHeight;
        imgOptions.width = ImageWidth;
        imgOptions.quality = ImageQuality;

        Xrm.Device.captureImage(imgOptions).then(
            function (imgData) {
                if (imgData != null && imgData != undefined && imgData.fileContent != null && imgData.fileContent != undefined && imgData.fileContent != "") {
                    var dataUri = imgData.fileContent;                    
                    var annotation = {};
                    annotation.documentbody = dataUri.replace("data:image/png;base64,", "");    
                    annotation.mimetype = "image/png";    
                    annotation["objectid_new_picture@odata.bind"] = "/new_pictures(" + parentRecordId + ")";
                    annotation.subject = "Attached Image : " + new Date().toLocaleString();
                    annotation.filename = fileName;
                    
                    //Create annotation using XRM
                }
            },
            function (error) {
                if (error != null && error != undefined && error != "" && error.message != null && error.message != undefined && error.message != "") {
                    Xrm.Navigation.openAlertDialog({ confirmButtonLabel: "Ok", text: error.message });                    
                } else {
                    Xrm.Navigation.openAlertDialog({ confirmButtonLabel: "Ok", text: error });
                }
            });
    }
}


As mentioned earlier, we end up with permission issue in Android when we set height, width, and allow edit image options (please refer below screenshot). Even we allow access camera, storage, and relevant components D365 client still popping up the same error. Once we removed image options it starts working without any issue. 



Once you remove image options from code then code will looks like following

function CaptureImage(event) {
    var parentRecordId = event.currentTarget.id;
    var fileName = parentRecordId + ":" + new Date().toLocaleString();
    var Client = globalContext.client.getClient();
    if (Client.toLocaleLowerCase() == "mobile") {
        Xrm.Device.captureImage().then(
            function (imgData) {
                if (imgData != null && imgData != undefined && imgData.fileContent != null && imgData.fileContent != undefined && imgData.fileContent != "") {
                    var dataUri = imgData.fileContent;                   
                    var annotation = {};
                    annotation.documentbody = dataUri.replace("data:image/png;base64,", "");   
                    annotation.mimetype = "image/png";   
                    annotation["objectid_new_picture@odata.bind"] = "/new_pictures(" + parentRecordId + ")";
                    annotation.subject = "Attached Image : " + new Date().toLocaleString();
                    annotation.filename = fileName;
                   
                    //Create annotation using XRM
                }
            },
            function (error) {
                if (error != null && error != undefined && error != "" && error.message != null && error.message != undefined && error.message != "") {
                    Xrm.Navigation.openAlertDialog({ confirmButtonLabel: "Ok", text: error.message });                   
                } else {
                    Xrm.Navigation.openAlertDialog({ confirmButtonLabel: "Ok", text: error });
                }
            });
    }
}


This work in both online and offline modes also both Android and iOS.

Saturday, August 22, 2020

D365 CE Tips: Enabling Mobile offline for users

 Microsoft provides details guide how to setup unified interface app for mobile and enabling offline capabilities. Please refer following Microsoft Document for setting up mobile capabilities for D365 CE.

 https://docs.microsoft.com/en-us/dynamics365/mobile-app/overview

However even after you complete all the steps users may not be able to enable offline capabilities of mobile CRM app. The main reason for that issue is, users may not have their offline profile configured in their user record. To fix that issue, you have to set Mobile Offline Profile for respective users. Following image shows how setting up Mobile Offline Profile for user.

After setting offline profile users should refresh their D365 Mobile app. After refreshing they can use D365 offline capabilities.




Friday, July 31, 2020

D365 CE Tips: Determine Mobile or Web in D365 CE using JavaScript

If you work with both CE Web and Mobile using Unified Interface, you may need to distinguish mobile client and web client inside your custom JavaScript. For example if you use single web resource for both CE web and CE mobile you have to distinguish both platforms to change your logic according to the platform.

Following code snippets will help you to distinguish platform based on the scenario.

Using GlobalContext

var globalContext = Xrm.Utility.getGlobalContext();
var Client = globalContext.client.getClient();


Using ExecutionContext

var Client = executionContext.context.client.getClient();

Value of Client variable will be “Web” or “Mobile” based on the platform. Hope this tip will be help. Enjoy 😊

Saturday, July 18, 2020

Resco Tricks: How to Fix Offline HTML Files not Updating issue in Resco Woodford Projects

If you use derived (hierarchical) Resco Woodford projects you may experience some time files are not updated even after you published all solutions. This article will help you to identify possible issues and resolve them.

For more details about Resco Woodford derived projects please refer following link


Scenario:
We have derived project structure like following
MSFieldService -> Survey -> ClientCustomizations


We have offline html file called “ReadOnlySurvey.htm” in survey solution. Due to an urgent production issue, development team replaced that offline html file directly in client customization Woodford project (top most project). However, in next production release development team deploy Survey Woodford project but after deployment they observed “ReadOnlySurvey.htm” file didn’t update and it did not contains all the changes did in development phase.


How to fix this issue:
Once offline html file manually override in the top most project without its own project, Woodford did not apply changes came through its original project any more. To apply changes from root project to top most project, files should be in “Inherited” state not in “Overridden” state.


To fix that before you import your root project (Survey project) to Resco, you have to restore the files you overridden before.
First you should open Woodford project which contains file you overridden before (in our case “ClientCustomization” project). Then select the relevant files and click restore button in the Woodford ribbon and save. Then system will restore the file from its root project. Then you can import your project (in our case Survey project) and publish them all.


This will fix your issue and apply changes to relevant files.

Monday, July 6, 2020

Unit Testing Dynamics 365 CE (CRM) Plugins/Actions

Unit testing is very important concept which ensure your code work without error and fulfill the requirement. Unit testing CRM plugins/actions are challenging because plugins and actions are executing under CRM context. If you create unit test project against CRM plugin project you have to mock CRM plugin context to unit test. Mocking CRM plugin context is not an easy task because it need lots of coding and it will be adding additional burden to the development.

There is a tool called “FakeXrmEasy” (https://dynamicsvalue.com/home) will remove that extra burden from development team and fake the CRM context. Using fake Xrm context we can unit test CRM plugins and actions without deploying them to CRM. This will help to debug CRM plugins as well.

Unit testing using FakeXrmEasy
I have create plugin project called “CEAutomation” and MSTest unit test project called “PluginUnitTest”.



I used MSTest (.Net Framework) as unit test project but there are several unit test frameworks available like NUnit, xUnit, etc.



Once you create unit test project you have to add FakeXrmEasy assemblies as NuGet Package. It will add Core CRM assemblies and necessary NuGet packages to your project.

Note: Please make sure you add correct version of FakeXrmEasy because there are several NuGet packages available for different versions of CRM.

In my case I use D365 CE online version, due to that reason I installed CRM 365 version supported version.


Test Scenario:
We have an online exam system which conduct exams through internet. After exam each and every candidate should fill out survey which collect their feedback about exam. Once they complete the survey, system will extract data for report. We implement CRM action to extract survey responses by sending survey id as an input parameter. Once action invoked with valid survey id, it query the CRM and retrieve all responses then convert responses to JSON string and return as output parameter.

We are going to create unit test for that CRM action. We are going to use FakeXrmEasy to create unit test and use XrmRealContext to connect to the CRM.

If our plugin implemented correctly once we feed valid CRM survey record id it should return the available responses list as JSON.

Plugin Code:

namespace CEAutomation.Response
{
    public class ResponseHandler : IPlugin
    {
        public IServiceProvider ServiceProvider
        {
            get;

            set;
        }

        public IOrganizationService OrganizationService
        {
            get;

            set;
        }

        public IPluginExecutionContext PluginExecutionContext
        {
            get;

            set;
        }

        public ITracingService TracingService
        {
            get;

            set;
        }

        public void Execute(IServiceProvider serviceProvider)
        {
            // Obtain the execution context service from the service provider.
            PluginExecutionContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

            // Obtain the tracing service from the service provider.
            TracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

            // Obtain the Organization Service factory service from the service provider
            IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

            OrganizationService = factory.CreateOrganizationService(PluginExecutionContext.UserId);

            if (PluginExecutionContext.InputParameters.Contains("SurveyId")
&& Guid.TryParse(PluginExecutionContext.InputParameters["SurveyId"].ToString(), out Guid surveyId) 
&& surveyId != Guid.Empty)

            {
                Survey.Survey survey = new Survey.Survey();
//Do What you want
                var responses = survey.GetSurveyResponsesJsonString(OrganizationService, TracingService, surveyId);
                PluginExecutionContext.OutputParameters["Responses"] = responses;
            }
        }

    }
}


Adding App.config to unit test project

Visual Studio not allowed to add Application Configuration file (App.config) file to unit test. We need to add it manually because we need to provide CRM connection string to XrmRealContext create connection. Since our project library does not contains App.config file we have to create it then include it to project using visual studio and set property to copy it to output directory. Add connection string as following and set copy to output directory property true in file properties.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="SurveyCRMDevInstance" connectionString="AuthType = Office365; Url = https://org.crm.dynamics.com/;Username=testusername@testdomain.onmicrosoft.com;Password=password" />
  </connectionStrings>
</configuration>


We named our CRM instance connection string as

SurveyCRMDevInstance”. You have to use same name when you initiate XrmRealContext.
To invoke plugin we have to supply survey id as input parameter named “SurveyId”. Once plugin executed it returns data as output parameter named “Responses”. In unit test we have to supply valid survey id as input parameter and we can extract result using output parameter.

Following code snippet will show how create unit test for action with input and output parameters.

[TestMethod]
public void RetrieveResponsesTest()
{
    try
    {
        var context = new XrmRealContext
        {
            ProxyTypesAssembly = typeof(ResponseHandler).Assembly,
            ConnectionStringName = "SurveyCRMDevInstance"
        };

        Guid.TryParse("9eab7684-fbb5-ea11-a812-000d3a305386", out Guid conductedSurveyId);

        var executionContext = context.GetDefaultPluginContext();
        executionContext.MessageName = "ResponseHandler";
        executionContext.InputParameters = new ParameterCollection
        {
            new KeyValuePair<string, object>("SurveyId", conductedSurveyId)
        };
        context.ExecutePluginWith<ResponseHandler>(executionContext);
        string outputString = executionContext.OutputParameters["Responses"].ToString();

        if (string.IsNullOrEmpty(outputString))
        {
            Assert.Fail("No result");
        }
        else
        {
            List<ebecssvy_responses> responseObjList = Utility.JsonToObject<List<ebecssvy_responses>>(outputString);

            Assert.AreNotEqual(0, responseObjList.Count, "List Contains Data");
        }

    }catch (Exception ex)
    {
        Assert.Fail(ex.Message);
    }
}



This can extend to unit test any plugin/action/custom workflow. We will post those special scenarios in future posts.
Happy Coding 😊

Saturday, June 13, 2020

Dynamics CE Tricks – Remove SLA from entity in CRM solution

There are few entity attributes which can enabled by solution but cannot disabled. Removing such properties not natively supported by Microsoft.
Those properties are,
    Feedback, Activities, Connections, Queues, Enable for SLA


Some of attributes may create new fields (most of time relationships) after enable (like SLA). If anyone accidently enabled one of those property there is no way to removed. There is an unsupported way to remove those properties.

However please try following steps with trial environment first and test before applying to any other environment.

Today we are going to remove SLA property from solution.
After enable SLA it creates two relationships and two fields between current entity and SLA related entities. First you have to export unmanaged solution. Also backup your environment using power platform before perform any change. In case you can restore backup instance.
Unzip your unmanaged solution first and open customization.xml file using xml support text editor.


Navigate to the relevant entity definition and set SLA flag value to 0


As mentioned in earlier enabling SLA will add few relationships and fields to the entity definition. We have to identify those fields and relationships and remove them. Open solution from CE and find extra fields and relationships
In our case we found two relationships added to our custom entity.
1.    manualsla_demo_tabs
2.    sla_demo_tabs


Remove them from customization.xml



Also there are 2 attributes. We also have to remove them from customization.xml as well.
1.    Slaid
2.    Slainvokeid





Before you pack your solution check it contains any missing dependency in solution.xml. If it has any please remove them from both solution.xml and customization.xml.

Once you completed previous stems you can select all components and zip. Renamed zip file with solution name you downloaded.


Note: Do not compress folder, it won’t import as solution.

Once you completed solution modification then tested it in trial environment before importing to any environment. If it functioning successfully you can import to any environment. To modify existing environment you have to backup all relevant entity data and delete entity. Or you can reset environment and import solution.


Saturday, May 30, 2020

Power Platform Analytics for Microsoft Dynamics 365 CE Part 2 - Common Data Service Analytics Part 1

This tab shows all common data service calls related statistics for further analysis. Using this developers can get more idea about following areas.

  •     Performance of Plugins/APIs/workflows
  •     Failure or pass rate of Plugins/APIs/Workflows
  •     Entity usage of dynamics CE
  •     User operations
  •     User access modes
  •     Mail box usage
We will describe each and every components in related section.
In the Home section it will show brief summary about Active Users, API Calls, API Pass Rate and Total Executions. Those data you can easily find out in relevant section with more details.


However first you need to set correct date range you need to analyze. You can set date range and environment as filters like following. This will apply for all other tabs and will show historical data according to the filter settings



Active Users Analytics

In this analytic group will show how many active users are in your system. To get more details about graphs I filtered data to single day.
First graph will show how many users are logged in to the given environment. If you select single day it will show data hourly or it will scale up based on the filters you added (e.g. If you select month it will show active users by day.



Following graph shows different operations performed by user based on time scale. This graph will show exact operation count by time and operation. This graph will help to get idea about mostly performed operations by time.


Following graph will show most active users based on the operations performed by user. This will help administrators to identify usage of CRM and who are the users most active. Also it will help to get idea about what are the operations which perform mostly and adjust CRM performance based on the operations. According to the example we have considerable amount of data reads than creates. We can optimize our read queries with “nolock” after some analysis about entities and data.



Total Operation graph helps to identify peak hours which system execute large number of operations. This will help administrators to change resource allocations plans dynamically. If you select filter criteria to years you can observe time periods which generate much traffic.


Total Page Request graph shows how much page requests generate by system/users in forms/reports/dashboards. At the moment current environment did not generate such request. However in live environments will get data in to this graph as well.


Tuesday, May 26, 2020

Power Platform Analytics for Microsoft Dynamics 365 CE Part 1 - Capacity

With recent power platform releases Microsoft introduce great combination of analytics which really helpful to analyze current CE instances and made decisions.

These analytics are crucial to keep CE instance with optimized performance. Also it helps relevant parties to made decisions.

How to navigate to “Power Platform Admin Center”




Then click admin link



Then move to All Admin Centers and open D365 admin center


Then open Analytics Tab

Note: You should have necessary D365 roles to open D365 admin page


Capacity:

In this tab will show database usage analysis. It will show how much disk space you’re used already, how much disk space remains. How much disk space used for database, logs and files. It will list down all the environments in your tenant. Once hover your mouse on the bar chart in bottom will show exact amount of each category (file/database).

Note: As I used trial environment it shows database as exceed. However if you use trial organization database space will not count.

Or you can use Storage Capacity tab to view those capacity data by category.

If you click on the chart icon in front of your CE environment name it will show more detailed analysis about your environment like below.

Note: You can export all these graphs and data through menu icon which placed top right hand corner button.
First chart will show top database usages based on category. User can delete unnecessary files/data based on this figures.



Also using following chart user can get idea about file storage and how it utilized. Based on that administrators can decide to remove unwanted annotations or solutions or any other unnecessary artifact to reduce file storage.


Last graph will show how space utilized for logs (plugin trace log).