Feeds:
Posts
Comments

Here are the steps needed in order to have cascading dropdowns in a Model driven app. Example: User selects a country and then selects state inside that country.

Example DataVerse structure:

  • A Country Table: holds names of countries
  • A State Table: hold names of State with a lookup to the country where the state belong
  • A Location Table: a custom table that has 2 lookups: one lookup for Country and another lookup for State

We can then create a model driven app with these 3 tables

We then need to go to the Location table Main form (or whatever form that is being used in the model driven app) and we need to add a JavaScript Web Resource

You can then simply click the Text Editor to paste the JavaScript code

The Code is

var Sdk = window.Sdk || {};
(function () {
    // Define some global variables
    var myUniqueId = "_myUniqueId"; // Define an ID for the notification
    var currentUserName = Xrm.Utility.getGlobalContext().userSettings.userName; // get current user name
    var message = currentUserName + ": Your JavaScript code in action!";

    // Code to run in the form OnLoad event
    this.formOnLoad = function (executionContext) {

    }

    // Code to run in the attribute OnChange event 
    this.attributeOnChange = function (executionContext) {
        
        var formContext = executionContext.getFormContext();

        var country = formContext.getAttribute("cr82b_country").getValue();
        if (country != null && country[0] != null) {
            formContext.ui.setFormNotification("Country=" + country[0].name, "INFO", myUniqueId);
            window.setTimeout(function () { formContext.ui.clearFormNotification(myUniqueId); }, 5000);
        }

        var stateControl = formContext.getControl("cr82b_state");
        stateControl.addPreSearch(Sdk.filterStates);
    }


    Sdk.filterStates = function () {

        var formContext = Xrm.Page.getControl("cr82b_country").formContext;
        var country = formContext.getAttribute("cr82b_country").getValue();
        if (country != null && country[0] != null) {
            var stateFilter = "<filter type='and'><condition attribute='cr82b_country' operator='eq' value='" + country[0].id + "'/></filter>";
            formContext.getControl("cr82b_state").addCustomFilter(stateFilter);
        }
    }

    // Code to run in the form OnSave event 
    this.formOnSave = function () {

    }
}).call(Sdk);

The main idea is to inject an OnChange Event to the Country Field and based on it, create a filter for States lookup

After publishing the script, refresh the Model driven app and you will see the filtering working (clicking “All records” after selecting a country, will only show states inside that country)

References:

addCustomFilter (Client API reference) in model-driven apps – Power Apps | Microsoft Docs

Filtering Lookups in Dynamics 365 with addCustomFilter and addPreSearch – Carl de Souza

Power Apps has two sets of rules for showing/hiding buttons: Display rules and Enable rules. Display rules are running on the server side and enable rules are running on the client site (maybe counterintuitive). Custom rules (JavaScript rules) are therefore only available in client side (Enable rules).

As an example, assumed we have two Tables (Parent and Child) with a one to many relation (Parent can have multiple children, child can only have one parent). We want to disable the “Deactivate” button on the Parent if it has children.

Preparations:

  1. In the make.powerapps.com, create 2 tables (Parent and Child) and set the relations between them
  2. Create a new Solution (example: RibbonEntitiesTest) and Add the two tables to it. This is needed for the Ribbon workbench to work.
  3. Create another Model driven application with the Parent and Child Tables for testing

Adding the JavaScript code with the logic:

  1. From make.powerapps.com, Select the table (Parent in our case) and Navigate to the

2) Navigate to the form where the ribbon is: (Main Information form for example)

3) Click the Form libraries tab on the left navigation

4) Click “Add Library” and then Click “New”

5) Set the library name, Type and Language

6) Either upload a new file or paste code directly in the Text Editor. Use the following code

var AB = AB || {};

AB.Ribbon = (function () {
    var isButtonEnabled = false;

    function IsButtonEnabled(formContext) {

        return new Promise(function (resolve, reject) {
            var Entity = "cr33f_child";
            var Select = "?$select=cr33f_name";
            var Filter = "&$filter=cr33f_Parent/new_parentid eq '" + formContext.data._entity._entityId.guid + "'";

            Xrm.WebApi.retrieveMultipleRecords(Entity, Select + Filter).then(
                function success(result) {
                    if (result.entities.length == 0) {
                        isButtonEnabled = true;
                    }

                    // return true or false
                    resolve(isButtonEnabled);
                },
                function (error) {
                    reject(error.message);
                    console.log(error.message);
                }
            );
        });
    }

    return {
        IsButtonEnabled: IsButtonEnabled
    };
})();

Note: you will have different prefixes (cr33f) and make sure of casing as the query is case sensitive

7) Click “Save” and “Publish”

Adding the new Rules to the ribbon:

  1. Download and install XrmToolBox from Home · XrmToolBox
  2. From XrmToolBox, open the “Ribbon Workbench” tool

3) In the Ribbon workbench, click “Open Solution” and select the solution that has the tables, in this example: RibbonEntitiesTest.

4) Select the entity whose ribbon we need to customize, in our case, parent entity

5) Select the button we need to customize and click “Customize Command” (NOT customize button)

6) Click the Command and in the Enable rules click “Add Enable rule”

7) Click “Add Step” and select “Custom Rule”

8) Set the function name, library name (use autocomplete feature) and Add parameter (Primary control)

9) Click “Publish” (sometimes it takes up to 10 minutes to complete)

10) Test ! you can check a parent entity with no related children should have the “Deactivate” button shown while a parent with related children should not

Troubleshooting

One simple way to troubleshoot is to add &ribbondebug=true to the url. this will show a new button called “Command Checker”

if you click it , you can see more information like

here is a simple code to load an image coming from a web service as byte array

In the html Add this snippet

   <a v-on:click="getQR">Get QR</a>

   <img id="qr" :src="qrImg" />

And add this snippet to the methods section in vuejs

getQR() {
      var base = this;
      axios
        .get(your api url + "/QRCode", { responseType: "arraybuffer" })
        .then(function (response) {

          let base64String = btoa(
            String.fromCharCode.apply(null, new Uint8Array(response.data))
          );
          base.qrImg = "data:image/jpg;base64," + base64String;
        });
    },

In Microsoft flow there is no built in action to add a user to a SharePoint group. One way to achieve this is to use the “Send HTTP request to SharePoint”

sendhttprequest

in this action you need to

  1. Set the URL of the Site
  2. Set method to “POST”
  3. URI set to “_api/web/sitegroups({GROUPID})/users”, example: _api/web/sitegroups(10)/users
  4. Add header with key=”accept” and value = “application/json;odata.metadata=none”
  5. Add header with key =”content-type” and value = “application/json”
  6. Set the Body to be {‘LoginName’:’i:0#.f|membership|[EMAIL ADDRESS]’}, example: {‘LoginName’:’i:0#.f|membership|john.doe@domain.onmicrosoft.com’}

It would look like this

sendhttprequest2

 

This is tested with a SharePoint online connection but assume might work with on premise SharePoint as well.

When trying to install SP2013 on a windows 2012R2 or 2016 you may get the error : Error: The tool was unable to install Application Server Role, Web Server (IIS) Role

A quick fix might be to go to C:\Windows\System32\ , look for ServerManager.exe, make a copy and name it ServerManagerCMD.exe as this is the file that the SP prereqs is trying to call

Reference: http://www.someshinyobject.com/posts/server-2012-r2-and-sharepoint-2013-the-tool-was-unable-to-install-application-server-role-web/

Newly released from Microsoft AI Lab, a tool to convert handwritten mockups into valid html code. Simply upload an image and  get HTML markup.

GitHub link: https://github.com/Microsoft/ailab/tree/master/Sketch2Code

a short YouTube video overview: https://www.youtube.com/watch?v=V6pqqPPHyYM

In order to replace a text in any section of the header or the footer of a word document, you can use this snippet

doc = Document Object

foreach (Section sec in doc.Sections)
{
foreach (HeaderFooter fot in sec.Footers)
{
fot.Range.Find.Execute(FindText: loc.Key, ReplaceWith: loc.Value,
Replace: WdReplace.wdReplaceAll);
}
}

I had a case of an IIS site that had link to a local ODT file (Office Document Text, used by Open office and star office).

Anyone clicking on this link was getting a 404 error, file not found. I made sure the url is correct, the file exists where it is supposed to be, etc..

After some investigation, it turned out that this file did not have its MIME type defined in IIS. As a result IIS was not serving an unknown MIME type: https://support.microsoft.com/en-us/help/326965/iis-6-0-does-not-serve-unknown-mime-types 

To fix this issue, simply add the MIME type to the designated site

  1. Open IIS Manager and navigate to the level you want to manage. For information about opening IIS Manager, see Open IIS Manager (IIS 7). For information about navigating to locations in the UI, see Navigation in IIS Manager (IIS 7).
  2. In Features View, double-click MIME Types.
  3. In the Actions pane, click Add.
  4. In the Add MIME Type dialog box, type a file name extension in the File name extension text box. For example, type .xyz.
  5. Type a MIME type in the MIME type text box. For example, type application/octet-stream.
  6. Click OK.

Ref: https://technet.microsoft.com/en-us/library/cc725608%28v=ws.10%29.aspx

To have http redirects in a sharepoint we can use something like this in the web.config file

<location path=”oldpage1.htm”>
<system.webServer>
<httpRedirect enabled=”true” destination=”newpage1.html” exactDestination=”true” httpResponseStatus=”Permanent” />
</system.webServer>
</location>

One simple way of doing it using PowerShell is to use the SPWebConfigModication object.

The following script can achieve that

 

$Owner = “redirectMod”
$webApp = Get-SPWebApplication $Url

 

$modification = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification
$modification.Path = “configuration”;
$modification.Name = “redirect-1” ;
$modification.Sequence = 0;
$modification.Owner =$Owner;
$modification.Type = 0 # EnsureChildNode;
$modification.Value = “<location path='”+$from+”‘><system.webServer><httpRedirect enabled=’true’ destination='”+$to+”‘ exactDestination=’true’ httpResponseStatus=’Permanent’ /></system.webServer></location>”;
$webApp.WebConfigModifications.Add($modification);

$webApp.Update()
$webApp.Parent.ApplyWebConfigModifications()
do{
Start-Sleep -Seconds 2;
Write-Host “.” -NoNewline
$configJobRunning = IsWebConfigModificationJobPendingOrRunning $webApp;
}while ($configJobRunning);

 

If we need to add some URL rewrite to a SharePoint site, we can do that using some web.config settings like :

<rewrite>
<rewriteMaps>
<rewriteMap name=”Redirects”>
<add key=”/Page1.html” value=”/Page1″ />
<add key=”/Page2.html” value=”/Page2″ />
</rewriteMap>
</rewriteMaps>
</rewrite>

One way to do that Is to use SharePoint Powershell commands.

The following script achieves that:
[Microsoft.SharePoint.Administration.SPWebConfigModification] $modification = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification
$modification.Path = “configuration/system.webServer”;
$modification.Name = “rewrite”;
$modification.Sequence = 0;
$modification.Owner =$Owner;
$modification.Type = 0 # EnsureChildNode;
$modification.Value = “”;
$webApp.WebConfigModifications.Add($modification);

$modification = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification
$modification.Path = “configuration/system.webServer/rewrite”;
$modification.Name = “rewriteMaps”;
$modification.Sequence = 0;
$modification.Owner =$Owner;
$modification.Type = 0 # EnsureChildNode;
$modification.Value = “”;
$webApp.WebConfigModifications.Add($modification);

$modification = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification
$modification.Path = “configuration/system.webServer/rewrite/rewriteMaps”;
$modification.Name = “rewriteMap”;
$modification.Sequence = 0;
$modification.Owner =$Owner;
$modification.Type = 0 # EnsureChildNode;
$modification.Value = “”;
$webApp.WebConfigModifications.Add($modification);

$modification = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification
$modification.Path = “configuration/system.webServer/rewrite/rewriteMaps/rewriteMap”;
$modification.Name = “redirect-1”;
$modification.Sequence = 0;
$modification.Owner =$Owner;
$modification.Type = 0 # EnsureChildNode;
$modification.Value = “”;
$webApp.WebConfigModifications.Add($modification);

$modification = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification
$modification.Path = “configuration/system.webServer/rewrite/rewriteMaps/rewriteMap”;
$modification.Name = “redirect-2”;
$modification.Sequence = 0;
$modification.Owner =$Owner;
$modification.Type = 0 # EnsureChildNode;
$modification.Value = “”;
$webApp.WebConfigModifications.Add($modification);

$webApp.Update()
$webApp.Parent.ApplyWebConfigModifications()

do{
Start-Sleep -Seconds 2;
Write-Host “.” -NoNewline
$configJobRunning = IsWebConfigModificationJobPendingOrRunning $webApp;
}while ($configJobRunning);

References:

https://blog.kenaro.com/2010/09/02/add-web-config-modification-with-powershell-spwebconfigmodification/ 

 https://docs.microsoft.com/en-us/iis/extensions/url-rewrite-module/using-rewrite-maps-in-url-rewrite-module